Merge tag 'efi-2019-07-rc1-2' of git://git.denx.de/u-boot-efi

Pull request for UEFI sub-system for v2019.07-rc1 (2)

In the aarch64 crash dump information about the loaded EFI images is added.

In README.uefi the development target is for the UEFI subsystem is
described as "Embedded Base Boot Requirements (EBBR) Specification"
compliance.

Several bug fixes are supplied.
diff --git a/Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt b/Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt
new file mode 100644
index 0000000..bac4afa
--- /dev/null
+++ b/Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt
@@ -0,0 +1,136 @@
+*** Reserved memory regions ***
+
+Reserved memory is specified as a node under the /reserved-memory node.
+The operating system shall exclude reserved memory from normal usage
+one can create child nodes describing particular reserved (excluded from
+normal use) memory regions. Such memory regions are usually designed for
+the special usage by various device drivers.
+
+Parameters for each memory region can be encoded into the device tree
+with the following nodes:
+
+/reserved-memory node
+---------------------
+#address-cells, #size-cells (required) - standard definition
+    - Should use the same values as the root node
+ranges (required) - standard definition
+    - Should be empty
+
+/reserved-memory/ child nodes
+-----------------------------
+Each child of the reserved-memory node specifies one or more regions of
+reserved memory. Each child node may either use a 'reg' property to
+specify a specific range of reserved memory, or a 'size' property with
+optional constraints to request a dynamically allocated block of memory.
+
+Following the generic-names recommended practice, node names should
+reflect the purpose of the node (ie. "framebuffer" or "dma-pool"). Unit
+address (@<address>) should be appended to the name if the node is a
+static allocation.
+
+Properties:
+Requires either a) or b) below.
+a) static allocation
+   reg (required) - standard definition
+b) dynamic allocation
+   size (required) - length based on parent's #size-cells
+                   - Size in bytes of memory to reserve.
+   alignment (optional) - length based on parent's #size-cells
+                        - Address boundary for alignment of allocation.
+   alloc-ranges (optional) - prop-encoded-array (address, length pairs).
+                           - Specifies regions of memory that are
+                             acceptable to allocate from.
+
+If both reg and size are present, then the reg property takes precedence
+and size is ignored.
+
+Additional properties:
+compatible (optional) - standard definition
+    - may contain the following strings:
+        - shared-dma-pool: This indicates a region of memory meant to be
+          used as a shared pool of DMA buffers for a set of devices. It can
+          be used by an operating system to instantiate the necessary pool
+          management subsystem if necessary.
+        - vendor specific string in the form <vendor>,[<device>-]<usage>
+no-map (optional) - empty property
+    - Indicates the operating system must not create a virtual mapping
+      of the region as part of its standard mapping of system memory,
+      nor permit speculative access to it under any circumstances other
+      than under the control of the device driver using the region.
+reusable (optional) - empty property
+    - The operating system can use the memory in this region with the
+      limitation that the device driver(s) owning the region need to be
+      able to reclaim it back. Typically that means that the operating
+      system can use that region to store volatile or cached data that
+      can be otherwise regenerated or migrated elsewhere.
+
+Linux implementation note:
+- If a "linux,cma-default" property is present, then Linux will use the
+  region for the default pool of the contiguous memory allocator.
+
+- If a "linux,dma-default" property is present, then Linux will use the
+  region for the default pool of the consistent DMA allocator.
+
+Device node references to reserved memory
+-----------------------------------------
+Regions in the /reserved-memory node may be referenced by other device
+nodes by adding a memory-region property to the device node.
+
+memory-region (optional) - phandle, specifier pairs to children of /reserved-memory
+
+Example
+-------
+This example defines 3 contiguous regions are defined for Linux kernel:
+one default of all device drivers (named linux,cma@72000000 and 64MiB in size),
+one dedicated to the framebuffer device (named framebuffer@78000000, 8MiB), and
+one for multimedia processing (named multimedia-memory@77000000, 64MiB).
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	memory {
+		reg = <0x40000000 0x40000000>;
+	};
+
+	reserved-memory {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		/* global autoconfigured region for contiguous allocations */
+		linux,cma {
+			compatible = "shared-dma-pool";
+			reusable;
+			size = <0x4000000>;
+			alignment = <0x2000>;
+			linux,cma-default;
+		};
+
+		display_reserved: framebuffer@78000000 {
+			reg = <0x78000000 0x800000>;
+		};
+
+		multimedia_reserved: multimedia@77000000 {
+			compatible = "acme,multimedia-memory";
+			reg = <0x77000000 0x4000000>;
+		};
+	};
+
+	/* ... */
+
+	fb0: video@12300000 {
+		memory-region = <&display_reserved>;
+		/* ... */
+	};
+
+	scaler: scaler@12500000 {
+		memory-region = <&multimedia_reserved>;
+		/* ... */
+	};
+
+	codec: codec@12600000 {
+		memory-region = <&multimedia_reserved>;
+		/* ... */
+	};
+};
diff --git a/MAINTAINERS b/MAINTAINERS
index f9ee428..c77abba 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -295,7 +295,9 @@
 F:	drivers/mmc/stm32_sdmmc2.c
 F:	drivers/phy/phy-stm32-usbphyc.c
 F:	drivers/pinctrl/pinctrl_stm32.c
+F:	drivers/power/pmic/stpmic1.c
 F:	drivers/power/regulator/stm32-vrefbuf.c
+F:	drivers/power/regulator/stpmic1.c
 F:	drivers/ram/stm32mp1/
 F:	drivers/misc/stm32_rcc.c
 F:	drivers/reset/stm32-reset.c
@@ -308,7 +310,7 @@
 F:	arch/arm/include/asm/arch-stv0991/
 
 ARM SUNXI
-M:	Jagan Teki <jagan@openedev.com>
+M:	Jagan Teki <jagan@amarulasolutions.com>
 M:	Maxime Ripard <maxime.ripard@bootlin.com>
 S:	Maintained
 T:	git git://git.denx.de/u-boot-sunxi.git
@@ -689,14 +691,14 @@
 F:	arch/sh/
 
 SPI
-M:	Jagan Teki <jagan@openedev.com>
+M:	Jagan Teki <jagan@amarulasolutions.com>
 S:	Maintained
 T:	git git://git.denx.de/u-boot-spi.git
 F:	drivers/spi/
 F:	include/spi*
 
 SPI-NOR
-M:	Jagan Teki <jagan@openedev.com>
+M:	Jagan Teki <jagan@amarulasolutions.com>
 M:	Vignesh R <vigneshr@ti.com>
 S:	Maintained
 F:	drivers/mtd/spi/
diff --git a/Makefile b/Makefile
index 9709e76..2824a6e 100644
--- a/Makefile
+++ b/Makefile
@@ -945,11 +945,22 @@
 	@echo >&2 "===================================================="
 endif
 endif
-ifeq ($(CONFIG_LIBATA)$(CONFIG_MVSATA_IDE),y)
-ifneq ($(CONFIG_DM_SCSI),y)
+ifeq ($(CONFIG_MVSATA_IDE),y)
+	@echo >&2 "===================== WARNING ======================"
+	@echo >&2 "This board does use CONFIG_MVSATA_IDE which is not"
+	@echo >&2 "ported to driver-model (DM) yet. Please update the storage"
+	@echo >&2 "controller driver to use CONFIG_AHCI before the v2019.07"
+	@echo >&2 "release."
+	@echo >&2 "Failure to update by the deadline may result in board removal."
+	@echo >&2 "See doc/driver-model/MIGRATION.txt for more info."
+	@echo >&2 "===================================================="
+endif
+ifeq ($(CONFIG_LIBATA),y)
+ifneq ($(CONFIG_AHCI),y)
 	@echo >&2 "===================== WARNING ======================"
-	@echo >&2 "This board does not use CONFIG_DM_SCSI. Please update"
-	@echo >&2 "the storage controller to use CONFIG_DM_SCSI before the v2019.07 release."
+	@echo >&2 "This board does use CONFIG_LIBATA but has CONFIG_AHCI not"
+	@echo >&2 "enabled. Please update the storage controller driver to use"
+	@echo >&2 "CONFIG_AHCI before the v2019.07 release."
 	@echo >&2 "Failure to update by the deadline may result in board removal."
 	@echo >&2 "See doc/driver-model/MIGRATION.txt for more info."
 	@echo >&2 "===================================================="
diff --git a/arch/arc/dts/axs10x_mb.dtsi b/arch/arc/dts/axs10x_mb.dtsi
index dfc0381..b5aacd5 100644
--- a/arch/arc/dts/axs10x_mb.dtsi
+++ b/arch/arc/dts/axs10x_mb.dtsi
@@ -71,7 +71,7 @@
 			clock-names = "spi_clk";
 			cs-gpio = <&cs_gpio 0>;
 			spi_flash@0 {
-				compatible = "spi-flash";
+				compatible = "jedec,spi-nor";
 				reg = <0>;
 				spi-max-frequency = <4000000>;
 			};
diff --git a/arch/arc/dts/hsdk.dts b/arch/arc/dts/hsdk.dts
index f024b96..5e9ba05 100644
--- a/arch/arc/dts/hsdk.dts
+++ b/arch/arc/dts/hsdk.dts
@@ -96,7 +96,7 @@
 		clock-names = "spi_clk";
 		cs-gpio = <&cs_gpio 0>;
 		spi_flash@0 {
-			compatible = "spi-flash";
+			compatible = "jedec,spi-nor";
 			reg = <0>;
 			spi-max-frequency = <4000000>;
 		};
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 398dbef..4640f3b 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1403,11 +1403,15 @@
 	select SYSRESET
 	select SYS_THUMB_BUILD
 	imply CMD_DM
+	imply CMD_POWEROFF
+	imply ENV_VARS_UBOOT_RUNTIME_CONFIG
 	help
 	  Support for STM32MP SoC family developed by STMicroelectronics,
 	  MPUs based on ARM cortex A core
-	  U-BOOT is running in DDR and SPL support is the unsecure First Stage
-	  BootLoader (FSBL)
+	  U-BOOT is running in DDR, loaded by the First Stage BootLoader (FSBL).
+	  FSBL can be TF-A: Trusted Firmware for Cortex A, for trusted boot
+	  chain.
+	  SPL is the unsecure FSBL for the basic boot chain.
 
 config ARCH_ROCKCHIP
 	bool "Support Rockchip SoCs"
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 65e0f66..8167cdb 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -138,7 +138,7 @@
 	armada-388-clearfog.dtb			\
 	armada-388-gp.dtb			\
 	armada-388-helios4.dtb			\
-	armada-385-amc.dtb			\
+	armada-385-db-88f6820-amc.dtb		\
 	armada-385-turris-omnia.dtb		\
 	armada-7040-db.dtb			\
 	armada-7040-db-nand.dtb			\
@@ -151,7 +151,8 @@
 	armada-xp-theadorable.dtb		\
 	armada-38x-controlcenterdc.dtb		\
 	armada-385-atl-x530.dtb			\
-	armada-385-atl-x530DP.dtb
+	armada-385-atl-x530DP.dtb		\
+	armada-xp-db-xc3-24g4xg.dtb
 
 dtb-$(CONFIG_ARCH_UNIPHIER_LD11) += \
 	uniphier-ld11-global.dtb \
@@ -475,6 +476,7 @@
 	sun50i-a64-amarula-relic.dtb \
 	sun50i-a64-bananapi-m64.dtb \
 	sun50i-a64-nanopi-a64.dtb \
+	sun50i-a64-oceanic-5205-5inmfd.dtb \
 	sun50i-a64-olinuxino.dtb \
 	sun50i-a64-orangepi-win.dtb \
 	sun50i-a64-pine64-lts.dtb \
@@ -686,6 +688,8 @@
 dtb-$(CONFIG_ARCH_STI) += stih410-b2260.dtb
 
 dtb-$(CONFIG_TARGET_STM32MP1) += \
+	stm32mp157a-dk1.dtb \
+	stm32mp157c-dk2.dtb \
 	stm32mp157c-ed1.dtb \
 	stm32mp157c-ev1.dtb
 
diff --git a/arch/arm/dts/am335x-brppt1-spi.dts b/arch/arm/dts/am335x-brppt1-spi.dts
index 522ed50..01ab74b 100644
--- a/arch/arm/dts/am335x-brppt1-spi.dts
+++ b/arch/arm/dts/am335x-brppt1-spi.dts
@@ -169,7 +169,7 @@
 	spi_flash: spiflash@0 {
 		u-boot,dm-spl;
 		u-boot,dm-pre-reloc;
-		compatible = "spidev", "spi-flash";
+		compatible = "spidev", "jedec,spi-nor";
 		spi-max-frequency = <24000000>;
 		reg = <0>;
 	};
diff --git a/arch/arm/dts/am437x-idk-evm.dts b/arch/arm/dts/am437x-idk-evm.dts
index 28e3e1b..19d1462 100644
--- a/arch/arm/dts/am437x-idk-evm.dts
+++ b/arch/arm/dts/am437x-idk-evm.dts
@@ -339,7 +339,7 @@
 
 	spi-max-frequency = <48000000>;
 	m25p80@0 {
-		compatible = "mx66l51235l", "spi-flash";
+		compatible = "mx66l51235l", "jedec,spi-nor";
 		spi-max-frequency = <48000000>;
 		reg = <0>;
 		spi-cpol;
diff --git a/arch/arm/dts/am437x-sk-evm.dts b/arch/arm/dts/am437x-sk-evm.dts
index 927d8d3..dc8fcde 100644
--- a/arch/arm/dts/am437x-sk-evm.dts
+++ b/arch/arm/dts/am437x-sk-evm.dts
@@ -568,7 +568,7 @@
 
 	spi-max-frequency = <48000000>;
 	m25p80@0 {
-		compatible = "mx66l51235l","spi-flash";
+		compatible = "mx66l51235l","jedec,spi-nor";
 		spi-max-frequency = <48000000>;
 		reg = <0>;
 		spi-cpol;
diff --git a/arch/arm/dts/armada-370-xp.dtsi b/arch/arm/dts/armada-370-xp.dtsi
index 0b2a78d..e4c35d4 100644
--- a/arch/arm/dts/armada-370-xp.dtsi
+++ b/arch/arm/dts/armada-370-xp.dtsi
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Device Tree Include file for Marvell Armada 370 and Armada XP SoC
  *
@@ -8,50 +9,10 @@
  * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
  * Ben Dooks <ben.dooks@codethink.co.uk>
  *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This file is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This file is distributed in the hope that it will be useful
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- * Or, alternatively
- *
- *  b) Permission is hereby granted, free of charge, to any person
- *     obtaining a copy of this software and associated documentation
- *     files (the "Software"), to deal in the Software without
- *     restriction, including without limitation the rights to use
- *     copy, modify, merge, publish, distribute, sublicense, and/or
- *     sell copies of the Software, and to permit persons to whom the
- *     Software is furnished to do so, subject to the following
- *     conditions:
- *
- *     The above copyright notice and this permission notice shall be
- *     included in all copies or substantial portions of the Software.
- *
- *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
- *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
- *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- *     OTHER DEALINGS IN THE SOFTWARE.
- *
  * This file contains the definitions that are common to the Armada
  * 370 and Armada XP SoC.
  */
 
-/include/ "skeleton64.dtsi"
-
 #define MBUS_ID(target,attributes) (((target) << 24) | ((attributes) << 16))
 
 / {
@@ -86,7 +47,7 @@
 		pcie-mem-aperture = <0xf8000000 0x7e00000>;
 		pcie-io-aperture  = <0xffe00000 0x100000>;
 
-		devbus-bootcs {
+		devbus_bootcs: devbus-bootcs {
 			compatible = "marvell,mvebu-devbus";
 			reg = <MBUS_ID(0xf0, 0x01) 0x10400 0x8>;
 			ranges = <0 MBUS_ID(0x01, 0x2f) 0 0xffffffff>;
@@ -96,7 +57,7 @@
 			status = "disabled";
 		};
 
-		devbus-cs0 {
+		devbus_cs0: devbus-cs0 {
 			compatible = "marvell,mvebu-devbus";
 			reg = <MBUS_ID(0xf0, 0x01) 0x10408 0x8>;
 			ranges = <0 MBUS_ID(0x01, 0x3e) 0 0xffffffff>;
@@ -106,7 +67,7 @@
 			status = "disabled";
 		};
 
-		devbus-cs1 {
+		devbus_cs1: devbus-cs1 {
 			compatible = "marvell,mvebu-devbus";
 			reg = <MBUS_ID(0xf0, 0x01) 0x10410 0x8>;
 			ranges = <0 MBUS_ID(0x01, 0x3d) 0 0xffffffff>;
@@ -116,7 +77,7 @@
 			status = "disabled";
 		};
 
-		devbus-cs2 {
+		devbus_cs2: devbus-cs2 {
 			compatible = "marvell,mvebu-devbus";
 			reg = <MBUS_ID(0xf0, 0x01) 0x10418 0x8>;
 			ranges = <0 MBUS_ID(0x01, 0x3b) 0 0xffffffff>;
@@ -126,7 +87,7 @@
 			status = "disabled";
 		};
 
-		devbus-cs3 {
+		devbus_cs3: devbus-cs3 {
 			compatible = "marvell,mvebu-devbus";
 			reg = <MBUS_ID(0xf0, 0x01) 0x10420 0x8>;
 			ranges = <0 MBUS_ID(0x01, 0x37) 0 0xffffffff>;
@@ -141,34 +102,13 @@
 			#address-cells = <1>;
 			#size-cells = <1>;
 			ranges = <0 MBUS_ID(0xf0, 0x01) 0 0x100000>;
-			u-boot,dm-pre-reloc;
 
-			rtc@10300 {
+			rtc: rtc@10300 {
 				compatible = "marvell,orion-rtc";
 				reg = <0x10300 0x20>;
 				interrupts = <50>;
 			};
 
-			spi0: spi@10600 {
-				reg = <0x10600 0x28>;
-				#address-cells = <1>;
-				#size-cells = <0>;
-				cell-index = <0>;
-				interrupts = <30>;
-				clocks = <&coreclk 0>;
-				status = "disabled";
-			};
-
-			spi1: spi@10680 {
-				reg = <0x10680 0x28>;
-				#address-cells = <1>;
-				#size-cells = <0>;
-				cell-index = <1>;
-				interrupts = <92>;
-				clocks = <&coreclk 0>;
-				status = "disabled";
-			};
-
 			i2c0: i2c@11000 {
 				compatible = "marvell,mv64xxx-i2c";
 				#address-cells = <1>;
@@ -235,33 +175,38 @@
 				msi-controller;
 			};
 
-			coherency-fabric@20200 {
+			coherencyfab: coherency-fabric@20200 {
 				compatible = "marvell,coherency-fabric";
 				reg = <0x20200 0xb0>, <0x21010 0x1c>;
 			};
 
-			timer@20300 {
+			timer: timer@20300 {
 				reg = <0x20300 0x30>, <0x21040 0x30>;
 				interrupts = <37>, <38>, <39>, <40>, <5>, <6>;
 			};
 
-			watchdog@20300 {
+			watchdog: watchdog@20300 {
 				reg = <0x20300 0x34>, <0x20704 0x4>;
 			};
 
-			pmsu@22000 {
+			cpurst: cpurst@20800 {
+				compatible = "marvell,armada-370-cpu-reset";
+				reg = <0x20800 0x8>;
+			};
+
+			pmsu: pmsu@22000 {
 				compatible = "marvell,armada-370-pmsu";
 				reg = <0x22000 0x1000>;
 			};
 
-			usb@50000 {
+			usb0: usb@50000 {
 				compatible = "marvell,orion-ehci";
 				reg = <0x50000 0x500>;
 				interrupts = <45>;
 				status = "disabled";
 			};
 
-			usb@51000 {
+			usb1: usb@51000 {
 				compatible = "marvell,orion-ehci";
 				reg = <0x51000 0x500>;
 				interrupts = <46>;
@@ -275,7 +220,7 @@
 				status = "disabled";
 			};
 
-			mdio: mdio {
+			mdio: mdio@72004 {
 				#address-cells = <1>;
 				#size-cells = <0>;
 				compatible = "marvell,orion-mdio";
@@ -290,7 +235,7 @@
 				status = "disabled";
 			};
 
-			sata@a0000 {
+			sata: sata@a0000 {
 				compatible = "marvell,armada-370-sata";
 				reg = <0xa0000 0x5000>;
 				interrupts = <55>;
@@ -309,7 +254,7 @@
 				status = "disabled";
 			};
 
-			mvsdio@d4000 {
+			sdio: mvsdio@d4000 {
 				compatible = "marvell,orion-sdio";
 				reg = <0xd4000 0x200>;
 				interrupts = <54>;
@@ -321,6 +266,42 @@
 				status = "disabled";
 			};
 		};
+
+		spi0: spi@10600 {
+			reg = <MBUS_ID(0xf0, 0x01) 0x10600 0x28>, /* control */
+			      <MBUS_ID(0x01, 0x1e) 0 0xffffffff>, /* CS0 */
+			      <MBUS_ID(0x01, 0x5e) 0 0xffffffff>, /* CS1 */
+			      <MBUS_ID(0x01, 0x9e) 0 0xffffffff>, /* CS2 */
+			      <MBUS_ID(0x01, 0xde) 0 0xffffffff>, /* CS3 */
+			      <MBUS_ID(0x01, 0x1f) 0 0xffffffff>, /* CS4 */
+			      <MBUS_ID(0x01, 0x5f) 0 0xffffffff>, /* CS5 */
+			      <MBUS_ID(0x01, 0x9f) 0 0xffffffff>, /* CS6 */
+			      <MBUS_ID(0x01, 0xdf) 0 0xffffffff>; /* CS7 */
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <0>;
+			interrupts = <30>;
+			clocks = <&coreclk 0>;
+			status = "disabled";
+		};
+
+		spi1: spi@10680 {
+			reg = <MBUS_ID(0xf0, 0x01) 0x10680 0x28>, /* control */
+			      <MBUS_ID(0x01, 0x1a) 0 0xffffffff>, /* CS0 */
+			      <MBUS_ID(0x01, 0x5a) 0 0xffffffff>, /* CS1 */
+			      <MBUS_ID(0x01, 0x9a) 0 0xffffffff>, /* CS2 */
+			      <MBUS_ID(0x01, 0xda) 0 0xffffffff>, /* CS3 */
+			      <MBUS_ID(0x01, 0x1b) 0 0xffffffff>, /* CS4 */
+			      <MBUS_ID(0x01, 0x5b) 0 0xffffffff>, /* CS5 */
+			      <MBUS_ID(0x01, 0x9b) 0 0xffffffff>, /* CS6 */
+			      <MBUS_ID(0x01, 0xdb) 0 0xffffffff>; /* CS7 */
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <1>;
+			interrupts = <92>;
+			clocks = <&coreclk 0>;
+			status = "disabled";
+		};
 	};
 
 	clocks {
diff --git a/arch/arm/dts/armada-3720-db.dts b/arch/arm/dts/armada-3720-db.dts
index 770c08a..1b219c4 100644
--- a/arch/arm/dts/armada-3720-db.dts
+++ b/arch/arm/dts/armada-3720-db.dts
@@ -131,7 +131,7 @@
 	spi-flash@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "st,m25p128", "spi-flash";
+		compatible = "st,m25p128", "jedec,spi-nor";
 		reg = <0>; /* Chip select 0 */
 		spi-max-frequency = <50000000>;
 		m25p,fast-read;
diff --git a/arch/arm/dts/armada-3720-espressobin.dts b/arch/arm/dts/armada-3720-espressobin.dts
index 7bfccb0..84e2c2a 100644
--- a/arch/arm/dts/armada-3720-espressobin.dts
+++ b/arch/arm/dts/armada-3720-espressobin.dts
@@ -118,7 +118,7 @@
 	spi-flash@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "st,m25p128", "spi-flash";
+		compatible = "st,m25p128", "jedec,spi-nor";
 		reg = <0>; /* Chip select 0 */
 		spi-max-frequency = <50000000>;
 		m25p,fast-read;
diff --git a/arch/arm/dts/armada-3720-turris-mox.dts b/arch/arm/dts/armada-3720-turris-mox.dts
index 14bec09..c36a5b8 100644
--- a/arch/arm/dts/armada-3720-turris-mox.dts
+++ b/arch/arm/dts/armada-3720-turris-mox.dts
@@ -115,7 +115,7 @@
 	spi-flash@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "st,s25fl064l", "spi-flash";
+		compatible = "st,s25fl064l", "jedec,spi-nor";
 		reg = <0>;
 		spi-max-frequency = <20000000>;
 		m25p,fast-read;
diff --git a/arch/arm/dts/armada-385-amc.dts b/arch/arm/dts/armada-385-amc.dts
deleted file mode 100644
index c9ccbb5..0000000
--- a/arch/arm/dts/armada-385-amc.dts
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Device Tree file for Marvell Armada 385 development board
- * (DB-88F6820-AMC)
- *
- * Copyright (C) 2014 Marvell
- *
- * Gregory CLEMENT <gregory.clement@free-electrons.com>
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This file is licensed under the terms of the GNU General Public
- *     License version 2.  This program is licensed "as is" without
- *     any warranty of any kind, whether express or implied.
- *
- * Or, alternatively,
- *
- *  b) Permission is hereby granted, free of charge, to any person
- *     obtaining a copy of this software and associated documentation
- *     files (the "Software"), to deal in the Software without
- *     restriction, including without limitation the rights to use,
- *     copy, modify, merge, publish, distribute, sublicense, and/or
- *     sell copies of the Software, and to permit persons to whom the
- *     Software is furnished to do so, subject to the following
- *     conditions:
- *
- *     The above copyright notice and this permission notice shall be
- *     included in all copies or substantial portions of the Software.
- *
- *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- *     OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/dts-v1/;
-#include "armada-385.dtsi"
-#include <dt-bindings/gpio/gpio.h>
-
-/ {
-	model = "Marvell Armada 385 AMC";
-	compatible = "marvell,a385-amc", "marvell,armada385", "marvell,armada380";
-
-	chosen {
-		stdout-path = "serial0:115200n8";
-	};
-
-	aliases {
-		ethernet0 = &eth0;
-		ethernet1 = &eth2;
-		i2c0 = &i2c0;
-		spi1 = &spi1;
-	};
-
-	memory {
-		device_type = "memory";
-		reg = <0x00000000 0x80000000>; /* 2 GB */
-	};
-
-	soc {
-		ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000
-			  MBUS_ID(0x01, 0x1d) 0 0xfff00000 0x100000>;
-
-		internal-regs {
-			i2c@11000 {
-				clock-frequency = <100000>;
-				u-boot,i2c-slave-addr = <0x0>;
-				pinctrl-names = "default";
-				pinctrl-0 = <&i2c0_pins>;
-				status = "okay";
-			};
-
-			serial@12000 {
-				/*
-				 * Exported on the micro USB connector CON16
-				 * through an FTDI
-				 */
-
-				pinctrl-names = "default";
-				pinctrl-0 = <&uart0_pins>;
-				status = "okay";
-				u-boot,dm-pre-reloc;
-			};
-
-			ethernet@34000 {
-				status = "okay";
-				phy = <&phy1>;
-				phy-mode = "sgmii";
-			};
-
-			usb@58000 {
-				status = "okay";
-			};
-
-			ethernet@70000 {
-				pinctrl-names = "default";
-				/*
-				 * The Reference Clock 0 is used to provide a
-				 * clock to the PHY
-				 */
-				pinctrl-0 = <&ge0_rgmii_pins>, <&ref_clk0_pins>;
-				status = "okay";
-				phy = <&phy0>;
-				phy-mode = "rgmii-id";
-			};
-
-
-			mdio@72004 {
-				pinctrl-names = "default";
-				pinctrl-0 = <&mdio_pins>;
-
-				phy0: ethernet-phy@1 {
-					reg = <1>;
-				};
-
-				phy1: ethernet-phy@0 {
-					reg = <0>;
-				};
-			};
-
-			flash@d0000 {
-				status = "okay";
-				num-cs = <1>;
-				marvell,nand-keep-config;
-				marvell,nand-enable-arbiter;
-				nand-on-flash-bbt;
-			};
-		};
-
-		pcie {
-			status = "okay";
-			pcie@1,0 {
-				/* Port 0, Lane 0 */
-				status = "okay";
-			};
-
-		};
-	};
-};
-
-&spi1 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&spi1_pins>;
-	status = "okay";
-	u-boot,dm-pre-reloc;
-
-	spi-flash@0 {
-		u-boot,dm-pre-reloc;
-		#address-cells = <1>;
-		#size-cells = <1>;
-		compatible = "st,m25p128", "jedec,spi-nor", "spi-flash";
-		reg = <0>; /* Chip select 0 */
-		spi-max-frequency = <50000000>;
-		m25p,fast-read;
-	};
-};
-
-&refclk {
-	clock-frequency = <20000000>;
-};
diff --git a/arch/arm/dts/armada-385-atl-x530-u-boot.dtsi b/arch/arm/dts/armada-385-atl-x530-u-boot.dtsi
index 7074a73..79b694c 100644
--- a/arch/arm/dts/armada-385-atl-x530-u-boot.dtsi
+++ b/arch/arm/dts/armada-385-atl-x530-u-boot.dtsi
@@ -11,3 +11,7 @@
 &uart0 {
 	u-boot,dm-pre-reloc;
 };
+
+&watchdog {
+	u-boot,dm-pre-reloc;
+};
diff --git a/arch/arm/dts/armada-385-db-88f6820-amc.dts b/arch/arm/dts/armada-385-db-88f6820-amc.dts
new file mode 100644
index 0000000..59a425f
--- /dev/null
+++ b/arch/arm/dts/armada-385-db-88f6820-amc.dts
@@ -0,0 +1,146 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Device Tree file for Marvell Armada 385 AMC board
+ * (DB-88F6820-AMC)
+ *
+ * Copyright (C) 2017 Allied Telesis Labs
+ */
+
+/dts-v1/;
+#include "armada-385.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	model = "Marvell Armada 385 AMC";
+	compatible = "marvell,a385-db-amc", "marvell,armada385", "marvell,armada380";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	aliases {
+		ethernet0 = &eth0;
+		ethernet1 = &eth2;
+		i2c0 = &i2c0;
+		spi1 = &spi1;
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x80000000>; /* 2GB */
+	};
+
+	soc {
+		ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000
+			  MBUS_ID(0x01, 0x1d) 0 0xfff00000 0x100000>;
+	};
+};
+
+&i2c0 {
+	u-boot,i2c-slave-addr = <0x0>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_pins>;
+	status = "okay";
+};
+
+&uart0 {
+	/*
+	 * Exported on the micro USB connector CON3
+	 * through an FTDI
+	 */
+
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pins>;
+	status = "okay";
+	u-boot,dm-pre-reloc;
+};
+
+
+&eth0 {
+	pinctrl-names = "default";
+	/*
+	 * The Reference Clock 0 is used to provide a
+	 * clock to the PHY
+	 */
+	pinctrl-0 = <&ge0_rgmii_pins>, <&ref_clk0_pins>;
+	status = "okay";
+	phy = <&phy0>;
+	phy-mode = "rgmii-id";
+};
+
+&eth2 {
+	status = "okay";
+	phy = <&phy1>;
+	phy-mode = "sgmii";
+};
+
+&usb0 {
+	status = "okay";
+};
+
+
+
+&mdio {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mdio_pins>;
+
+	phy0: ethernet-phy@1 {
+		reg = <1>;
+	};
+
+	phy1: ethernet-phy@0 {
+		reg = <0>;
+	};
+};
+
+&nand_controller {
+	status = "okay";
+	marvell,nand-keep-config;
+	marvell,nand-enable-arbiter;
+	nand-on-flash-bbt;
+};
+
+&pciec {
+	status = "okay";
+};
+
+&pcie1 {
+	/* Port 0, Lane 0 */
+	status = "okay";
+};
+
+&spi1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi1_pins>;
+	status = "okay";
+	u-boot,dm-pre-reloc;
+
+	spi-flash@0 {
+		u-boot,dm-pre-reloc;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "jedec,spi-nor";
+		reg = <0>; /* Chip select 0 */
+		spi-max-frequency = <50000000>;
+		m25p,fast-read;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			partition@0 {
+				reg = <0x00000000 0x00100000>;
+				label = "u-boot";
+			};
+			partition@100000 {
+				reg = <0x00100000 0x00040000>;
+				label = "u-boot-env";
+			};
+		};
+	};
+};
+
+&refclk {
+	clock-frequency = <20000000>;
+};
diff --git a/arch/arm/dts/armada-385-turris-omnia-u-boot.dtsi b/arch/arm/dts/armada-385-turris-omnia-u-boot.dtsi
index 904429b..1b46797 100644
--- a/arch/arm/dts/armada-385-turris-omnia-u-boot.dtsi
+++ b/arch/arm/dts/armada-385-turris-omnia-u-boot.dtsi
@@ -42,7 +42,7 @@
 	u-boot,dm-pre-reloc;
 
 	spi-flash@0 {
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		reg = <0>;
 		spi-max-frequency = <40000000>;
 		u-boot,dm-pre-reloc;
diff --git a/arch/arm/dts/armada-38x-controlcenterdc.dts b/arch/arm/dts/armada-38x-controlcenterdc.dts
index bad7c60..5063a79 100644
--- a/arch/arm/dts/armada-38x-controlcenterdc.dts
+++ b/arch/arm/dts/armada-38x-controlcenterdc.dts
@@ -573,14 +573,14 @@
 	spi-flash@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "n25q016a", "spi-flash";
+		compatible = "n25q016a", "jedec,spi-nor";
 		reg = <0>; /* Chip select 0 */
 		spi-max-frequency = <108000000>;
 	};
 	spi-flash@1 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "n25q128a11", "spi-flash";
+		compatible = "n25q128a11", "jedec,spi-nor";
 		reg = <1>; /* Chip select 1 */
 		spi-max-frequency = <108000000>;
 		u-boot,dm-pre-reloc;
diff --git a/arch/arm/dts/armada-38x-solidrun-microsom.dtsi b/arch/arm/dts/armada-38x-solidrun-microsom.dtsi
index 74f58de..a262722 100644
--- a/arch/arm/dts/armada-38x-solidrun-microsom.dtsi
+++ b/arch/arm/dts/armada-38x-solidrun-microsom.dtsi
@@ -86,7 +86,7 @@
 	w25q32: spi-flash@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "w25q32", "jedec,spi-nor", "spi-flash";
+		compatible = "w25q32", "jedec,spi-nor";
 		reg = <0>; /* Chip select 0 */
 		spi-max-frequency = <3000000>;
 		status = "disabled";
diff --git a/arch/arm/dts/armada-8040-clearfog-gt-8k.dts b/arch/arm/dts/armada-8040-clearfog-gt-8k.dts
index cdff44a..720c950 100644
--- a/arch/arm/dts/armada-8040-clearfog-gt-8k.dts
+++ b/arch/arm/dts/armada-8040-clearfog-gt-8k.dts
@@ -240,7 +240,7 @@
 	status = "okay";
 
 	spi-flash@0 {
-		compatible = "jedec,spi-nor", "spi-flash";
+		compatible = "jedec,spi-nor";
 		reg = <0>;
 		spi-max-frequency = <10000000>;
 
diff --git a/arch/arm/dts/armada-xp-98dx3236.dtsi b/arch/arm/dts/armada-xp-98dx3236.dtsi
new file mode 100644
index 0000000..5df1d18
--- /dev/null
+++ b/arch/arm/dts/armada-xp-98dx3236.dtsi
@@ -0,0 +1,343 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Device Tree Include file for Marvell 98dx3236 family SoC
+ *
+ * Copyright (C) 2016 Allied Telesis Labs
+ *
+ * Contains definitions specific to the 98dx3236 SoC that are not
+ * common to all Armada XP SoCs.
+ */
+
+#include "armada-370-xp.dtsi"
+
+/ {
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	model = "Marvell 98DX3236 SoC";
+	compatible = "marvell,armadaxp-98dx3236", "marvell,armada-370-xp";
+
+	aliases {
+		gpio0 = &gpio0;
+		gpio1 = &gpio1;
+		gpio2 = &gpio2;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		enable-method = "marvell,98dx3236-smp";
+
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "marvell,sheeva-v7";
+			reg = <0>;
+			clocks = <&cpuclk 0>;
+			clock-latency = <1000000>;
+		};
+	};
+
+	soc {
+		compatible = "marvell,armadaxp-mbus", "simple-bus";
+
+		ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xf1000000 0x100000
+			  MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000
+			  MBUS_ID(0x01, 0x2f) 0 0 0xf0000000 0x1000000
+			  MBUS_ID(0x03, 0x00) 0 0 0xa8000000 0x4000000
+			  MBUS_ID(0x08, 0x00) 0 0 0xac000000 0x100000>;
+
+		bootrom {
+			compatible = "marvell,bootrom";
+			reg = <MBUS_ID(0x01, 0x1d) 0 0x100000>;
+		};
+
+		/*
+		 * 98DX3236 has 1 x1 PCIe unit Gen2.0
+		 */
+		pciec: pcie@82000000 {
+			compatible = "marvell,armada-xp-pcie";
+			status = "disabled";
+			device_type = "pci";
+
+			#address-cells = <3>;
+			#size-cells = <2>;
+
+			msi-parent = <&mpic>;
+			bus-range = <0x00 0xff>;
+
+			ranges =
+			       <0x82000000 0 0x40000 MBUS_ID(0xf0, 0x01) 0x40000 0 0x00002000   /* Port 0.0 registers */
+				0x82000000 0x1 0       MBUS_ID(0x04, 0xe8) 0 1 0 /* Port 0.0 MEM */
+				0x81000000 0x1 0       MBUS_ID(0x04, 0xe0) 0 1 0 /* Port 0.0 IO  */>;
+
+			pcie1: pcie@1,0 {
+				device_type = "pci";
+				assigned-addresses = <0x82000800 0 0x40000 0 0x2000>;
+				reg = <0x0800 0 0 0 0>;
+				#address-cells = <3>;
+				#size-cells = <2>;
+				#interrupt-cells = <1>;
+				ranges = <0x82000000 0 0 0x82000000 0x1 0 1 0
+					  0x81000000 0 0 0x81000000 0x1 0 1 0>;
+				bus-range = <0x00 0xff>;
+				interrupt-map-mask = <0 0 0 0>;
+				interrupt-map = <0 0 0 0 &mpic 58>;
+				marvell,pcie-port = <0>;
+				marvell,pcie-lane = <0>;
+				clocks = <&gateclk 5>;
+				status = "disabled";
+			};
+		};
+
+		internal-regs {
+			sdramc: sdramc@1400 {
+				compatible = "marvell,armada-xp-sdram-controller";
+				reg = <0x1400 0x500>;
+			};
+
+			L2: l2-cache@8000 {
+				compatible = "marvell,aurora-system-cache";
+				reg = <0x08000 0x1000>;
+				cache-id-part = <0x100>;
+				cache-level = <2>;
+				cache-unified;
+				wt-override;
+			};
+
+			gpio0: gpio@18100 {
+				compatible = "marvell,orion-gpio";
+				reg = <0x18100 0x40>;
+				ngpios = <32>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				interrupts = <82>, <83>, <84>, <85>;
+			};
+
+			/* does not exist */
+			gpio1: gpio@18140 {
+				compatible = "marvell,orion-gpio";
+				reg = <0x18140 0x40>;
+				status = "disabled";
+			};
+
+			gpio2: gpio@18180 { /* rework some properties */
+				compatible = "marvell,orion-gpio";
+				reg = <0x18180 0x40>;
+				ngpios = <1>; /* only gpio #32 */
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				interrupts = <87>;
+			};
+
+			systemc: system-controller@18200 {
+				compatible = "marvell,armada-370-xp-system-controller";
+				reg = <0x18200 0x500>;
+			};
+
+			gateclk: clock-gating-control@18220 {
+				compatible = "marvell,mv98dx3236-gating-clock";
+				reg = <0x18220 0x4>;
+				clocks = <&coreclk 0>;
+				#clock-cells = <1>;
+			};
+
+			cpuclk: clock-complex@18700 {
+				#clock-cells = <1>;
+				compatible = "marvell,mv98dx3236-cpu-clock";
+				reg = <0x18700 0x24>, <0x1c054 0x10>;
+				clocks = <&coreclk 1>;
+			};
+
+			corediv-clock@18740 {
+				status = "disabled";
+			};
+
+			cpu-config@21000 {
+				compatible = "marvell,armada-xp-cpu-config";
+				reg = <0x21000 0x8>;
+			};
+
+			ethernet@70000 {
+				compatible = "marvell,armada-xp-neta";
+			};
+
+			ethernet@74000 {
+				compatible = "marvell,armada-xp-neta";
+			};
+
+			xor1: xor@f0800 {
+				compatible = "marvell,orion-xor";
+				reg = <0xf0800 0x100
+				       0xf0a00 0x100>;
+				clocks = <&gateclk 22>;
+				status = "okay";
+
+				xor10 {
+					interrupts = <51>;
+					dmacap,memcpy;
+					dmacap,xor;
+				};
+				xor11 {
+					interrupts = <52>;
+					dmacap,memcpy;
+					dmacap,xor;
+					dmacap,memset;
+				};
+			};
+
+			nand_controller: nand@d0000 {
+				clocks = <&dfx_coredivclk 0>;
+			};
+
+			xor0: xor@f0900 {
+				compatible = "marvell,orion-xor";
+				reg = <0xF0900 0x100
+				       0xF0B00 0x100>;
+				clocks = <&gateclk 28>;
+				status = "okay";
+
+				xor00 {
+					interrupts = <94>;
+					dmacap,memcpy;
+					dmacap,xor;
+				};
+				xor01 {
+					interrupts = <95>;
+					dmacap,memcpy;
+					dmacap,xor;
+					dmacap,memset;
+				};
+			};
+		};
+
+		dfx: dfx-server@ac000000 {
+			compatible = "marvell,dfx-server", "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 MBUS_ID(0x08, 0x00) 0 0x100000>;
+			reg = <MBUS_ID(0x08, 0x00) 0 0x100000>;
+
+                        thermal: thermal@f8078 {
+                                compatible = "marvell,armada380-thermal";
+                                reg = <0xf8078 0x4>, <0xf8074 0x4>;
+                                status = "okay";
+                        };
+
+			coreclk: mvebu-sar@f8204 {
+				compatible = "marvell,mv98dx3236-core-clock";
+				reg = <0xf8204 0x4>;
+				#clock-cells = <1>;
+			};
+
+			dfx_coredivclk: corediv-clock@f8268 {
+				compatible = "marvell,mv98dx3236-corediv-clock";
+				reg = <0xf8268 0xc>;
+				#clock-cells = <1>;
+				clocks = <&mainpll>;
+				clock-output-names = "nand";
+			};
+		};
+
+		switch: switch@a8000000 {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 MBUS_ID(0x03, 0x00) 0 0x100000>;
+
+			pp0: packet-processor@0 {
+				compatible = "marvell,prestera-98dx3236", "marvell,prestera";
+				reg = <0 0x4000000>;
+				interrupts = <33>, <34>, <35>;
+				dfx = <&dfx>;
+			};
+		};
+	};
+
+	clocks {
+		/* 25 MHz reference crystal */
+		refclk: oscillator {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <25000000>;
+		};
+	};
+};
+
+&i2c0 {
+	compatible = "marvell,mv78230-i2c", "marvell,mv64xxx-i2c";
+	reg = <0x11000 0x100>;
+};
+
+&i2c1 {
+	compatible = "marvell,mv78230-i2c", "marvell,mv64xxx-i2c";
+	reg = <0x11100 0x100>;
+};
+
+&mpic {
+	reg = <0x20a00 0x2d0>, <0x21070 0x58>;
+};
+
+&rtc {
+	status = "disabled";
+};
+
+&timer {
+	compatible = "marvell,armada-xp-timer";
+	clocks = <&coreclk 2>, <&refclk>;
+	clock-names = "nbclk", "fixed";
+};
+
+&watchdog {
+	compatible = "marvell,armada-xp-wdt";
+	clocks = <&coreclk 2>, <&refclk>;
+	clock-names = "nbclk", "fixed";
+};
+
+&cpurst {
+	reg = <0x20800 0x20>;
+};
+
+&usb0 {
+	clocks = <&gateclk 18>;
+};
+
+&usb1 {
+	clocks = <&gateclk 19>;
+};
+
+&pinctrl {
+	compatible = "marvell,98dx3236-pinctrl";
+
+	nand_pins: nand-pins {
+		marvell,pins = "mpp20", "mpp21", "mpp22",
+			       "mpp23", "mpp24", "mpp25",
+			       "mpp26", "mpp27", "mpp28",
+			       "mpp29", "mpp30";
+		marvell,function = "dev";
+	};
+
+	nand_rb: nand-rb {
+		marvell,pins = "mpp19";
+		marvell,function = "nand";
+	};
+
+	spi0_pins: spi0-pins {
+		marvell,pins = "mpp0", "mpp1",
+			       "mpp2", "mpp3";
+		marvell,function = "spi0";
+	};
+};
+
+&spi0 {
+	compatible = "marvell,armada-xp-spi", "marvell,orion-spi";
+	pinctrl-0 = <&spi0_pins>;
+	pinctrl-names = "default";
+};
+
+&sdio {
+	status = "disabled";
+};
diff --git a/arch/arm/dts/armada-xp-98dx3336.dtsi b/arch/arm/dts/armada-xp-98dx3336.dtsi
new file mode 100644
index 0000000..1d9d8a8
--- /dev/null
+++ b/arch/arm/dts/armada-xp-98dx3336.dtsi
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Device Tree Include file for Marvell 98dx3336 family SoC
+ *
+ * Copyright (C) 2016 Allied Telesis Labs
+ *
+ * Contains definitions specific to the 98dx3236 SoC that are not
+ * common to all Armada XP SoCs.
+ */
+
+#include "armada-xp-98dx3236.dtsi"
+
+/ {
+	model = "Marvell 98DX3336 SoC";
+	compatible = "marvell,armadaxp-98dx3336", "marvell,armadaxp-98dx3236", "marvell,armada-370-xp";
+
+	cpus {
+		cpu@1 {
+			device_type = "cpu";
+			compatible = "marvell,sheeva-v7";
+			reg = <1>;
+			clocks = <&cpuclk 1>;
+			clock-latency = <1000000>;
+		};
+	};
+
+	soc {
+		internal-regs {
+			resume@20980 {
+				compatible = "marvell,98dx3336-resume-ctrl";
+				reg = <0x20980 0x10>;
+			};
+		};
+	};
+};
+
+&pp0 {
+	compatible = "marvell,prestera-98dx3336", "marvell,prestera";
+};
diff --git a/arch/arm/dts/armada-xp-98dx4251.dtsi b/arch/arm/dts/armada-xp-98dx4251.dtsi
new file mode 100644
index 0000000..48ffdc7
--- /dev/null
+++ b/arch/arm/dts/armada-xp-98dx4251.dtsi
@@ -0,0 +1,54 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Device Tree Include file for Marvell 98dx4521 family SoC
+ *
+ * Copyright (C) 2016 Allied Telesis Labs
+ *
+ * Contains definitions specific to the 98dx4521 SoC that are not
+ * common to all Armada XP SoCs.
+ */
+
+#include "armada-xp-98dx3236.dtsi"
+
+/ {
+	model = "Marvell 98DX4251 SoC";
+	compatible = "marvell,armadaxp-98dx4251", "marvell,armadaxp-98dx3236", "marvell,armada-370-xp";
+
+	cpus {
+		cpu@1 {
+			device_type = "cpu";
+			compatible = "marvell,sheeva-v7";
+			reg = <1>;
+			clocks = <&cpuclk 1>;
+			clock-latency = <1000000>;
+		};
+	};
+
+	soc {
+		internal-regs {
+			resume@20980 {
+				compatible = "marvell,98dx3336-resume-ctrl";
+				reg = <0x20980 0x10>;
+			};
+		};
+	};
+};
+
+&sdio {
+	status = "okay";
+};
+
+&pinctrl {
+	compatible = "marvell,98dx4251-pinctrl";
+
+	sdio_pins: sdio-pins {
+		marvell,pins = "mpp5", "mpp6", "mpp7",
+			       "mpp8", "mpp9", "mpp10";
+		marvell,function = "sd0";
+	};
+};
+
+&pp0 {
+	compatible = "marvell,prestera-98dx4251", "marvell,prestera";
+	interrupts = <33>, <34>, <35>, <36>;
+};
diff --git a/arch/arm/dts/armada-xp-db-xc3-24g4xg-u-boot.dtsi b/arch/arm/dts/armada-xp-db-xc3-24g4xg-u-boot.dtsi
new file mode 100644
index 0000000..90cad85
--- /dev/null
+++ b/arch/arm/dts/armada-xp-db-xc3-24g4xg-u-boot.dtsi
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+&uart0 {
+	u-boot,dm-pre-reloc;
+};
+
+&nand_controller {
+	compatible="marvell,mvebu-pxa3xx-nand";
+	status = "okay";
+	label = "pxa3xx_nand-0";
+	nand-rb = <0>;
+	marvell,nand-keep-config;
+	nand-on-flash-bbt;
+	nand-ecc-strength = <4>;
+	nand-ecc-step-size = <512>;
+};
+
+&spi0 {
+	u-boot,dm-pre-reloc;
+
+	spi-flash@0 {
+		u-boot,dm-pre-reloc;
+	};
+};
diff --git a/arch/arm/dts/armada-xp-db-xc3-24g4xg.dts b/arch/arm/dts/armada-xp-db-xc3-24g4xg.dts
new file mode 100644
index 0000000..d4b5288
--- /dev/null
+++ b/arch/arm/dts/armada-xp-db-xc3-24g4xg.dts
@@ -0,0 +1,110 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Device Tree file for DB-XC3-24G4XG board
+ *
+ * Copyright (C) 2016 Allied Telesis Labs
+ *
+ * Based on armada-xp-db.dts
+ *
+ * Note: this Device Tree assumes that the bootloader has remapped the
+ * internal registers to 0xf1000000 (instead of the default
+ * 0xd0000000). The 0xf1000000 is the default used by the recent,
+ * DT-capable, U-Boot bootloaders provided by Marvell. Some earlier
+ * boards were delivered with an older version of the bootloader that
+ * left internal registers mapped at 0xd0000000. If you are in this
+ * situation, you should either update your bootloader (preferred
+ * solution) or the below Device Tree should be adjusted.
+ */
+
+/dts-v1/;
+#include "armada-xp-98dx3336.dtsi"
+#include "armada-xp-db-xc3-24g4xg-u-boot.dtsi"
+
+/ {
+	model = "DB-XC3-24G4XG";
+	compatible = "marvell,armadaxp-98dx3336", "marvell,armadaxp-mv78260", "marvell,armadaxp", "marvell,armada-370-xp";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+		bootargs = "console=ttyS0,115200 earlyprintk";
+	};
+
+	aliases {
+		spi0 = &spi0;
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0 0x00000000 0 0x40000000>; /* 1 GB */
+	};
+};
+
+&L2 {
+	arm,parity-enable;
+	marvell,ecc-enable;
+};
+
+&devbus_bootcs {
+	status = "okay";
+
+	/* Device Bus parameters are required */
+
+	/* Read parameters */
+	devbus,bus-width    = <16>;
+	devbus,turn-off-ps  = <60000>;
+	devbus,badr-skew-ps = <0>;
+	devbus,acc-first-ps = <124000>;
+	devbus,acc-next-ps  = <248000>;
+	devbus,rd-setup-ps  = <0>;
+	devbus,rd-hold-ps   = <0>;
+
+	/* Write parameters */
+	devbus,sync-enable = <0>;
+	devbus,wr-high-ps  = <60000>;
+	devbus,wr-low-ps   = <60000>;
+	devbus,ale-wr-ps   = <60000>;
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&uart1 {
+	status = "okay";
+};
+
+&i2c0 {
+	clock-frequency = <100000>;
+	status = "okay";
+};
+
+&usb0 {
+	status = "okay";
+};
+
+&spi0 {
+	status = "okay";
+
+	spi-flash@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "spi-flash", "jedec,spi-nor";
+		reg = <0>; /* Chip select 0 */
+		spi-max-frequency = <108000000>;
+		m25p,fast-read;
+
+		partition@u-boot {
+			reg = <0x00000000 0x00100000>;
+			label = "u-boot";
+		};
+		partition@u-boot-env {
+			reg = <0x00100000 0x00040000>;
+			label = "u-boot-env";
+		};
+		partition@unused {
+			reg = <0x00140000 0x00ec0000>;
+			label = "unused";
+		};
+
+	};
+};
diff --git a/arch/arm/dts/armada-xp-gp.dts b/arch/arm/dts/armada-xp-gp.dts
index 27799d1..1139e94 100644
--- a/arch/arm/dts/armada-xp-gp.dts
+++ b/arch/arm/dts/armada-xp-gp.dts
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Device Tree file for Marvell Armada XP development board
  * (DB-MV784MP-GP)
@@ -8,44 +9,6 @@
  * Gregory CLEMENT <gregory.clement@free-electrons.com>
  * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
  *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This file is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This file is distributed in the hope that it will be useful
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- * Or, alternatively
- *
- *  b) Permission is hereby granted, free of charge, to any person
- *     obtaining a copy of this software and associated documentation
- *     files (the "Software"), to deal in the Software without
- *     restriction, including without limitation the rights to use
- *     copy, modify, merge, publish, distribute, sublicense, and/or
- *     sell copies of the Software, and to permit persons to whom the
- *     Software is furnished to do so, subject to the following
- *     conditions:
- *
- *     The above copyright notice and this permission notice shall be
- *     included in all copies or substantial portions of the Software.
- *
- *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
- *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
- *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- *     OTHER DEALINGS IN THE SOFTWARE.
- *
  * Note: this Device Tree assumes that the bootloader has remapped the
  * internal registers to 0xf1000000 (instead of the default
  * 0xd0000000). The 0xf1000000 is the default used by the recent,
@@ -68,11 +31,7 @@
 		stdout-path = "serial0:115200n8";
 	};
 
-	aliases {
-		spi0 = &spi0;
-	};
-
-	memory {
+	memory@0 {
 		device_type = "memory";
 		/*
                  * 8 GB of plug-in RAM modules by default.The amount
@@ -98,7 +57,10 @@
 	soc {
 		ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xf1000000 0x100000
 			  MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000
-			  MBUS_ID(0x01, 0x2f) 0 0 0xf0000000 0x1000000>;
+			  MBUS_ID(0x01, 0x2f) 0 0 0xf0000000 0x1000000
+			  MBUS_ID(0x09, 0x09) 0 0 0xf1100000 0x10000
+			  MBUS_ID(0x09, 0x05) 0 0 0xf1110000 0x10000
+			  MBUS_ID(0x0c, 0x04) 0 0 0xf1200000 0x100000>;
 
 		devbus-bootcs {
 			status = "okay";
@@ -128,31 +90,9 @@
 			};
 		};
 
-		pcie-controller {
-			status = "okay";
-
-			/*
-			 * The 3 slots are physically present as
-			 * standard PCIe slots on the board.
-			 */
-			pcie@1,0 {
-				/* Port 0, Lane 0 */
-				status = "okay";
-			};
-			pcie@9,0 {
-				/* Port 2, Lane 0 */
-				status = "okay";
-			};
-			pcie@10,0 {
-				/* Port 3, Lane 0 */
-				status = "okay";
-			};
-		};
-
 		internal-regs {
 			serial@12000 {
 				status = "okay";
-				u-boot,dm-pre-reloc;
 			};
 			serial@12100 {
 				status = "okay";
@@ -177,43 +117,33 @@
 				status = "okay";
 			};
 
-			mdio {
-				phy0: ethernet-phy@0 {
-					reg = <16>;
-				};
-
-				phy1: ethernet-phy@1 {
-					reg = <17>;
-				};
-
-				phy2: ethernet-phy@2 {
-					reg = <18>;
-				};
-
-				phy3: ethernet-phy@3 {
-					reg = <19>;
-				};
-			};
-
 			ethernet@70000 {
 				status = "okay";
 				phy = <&phy0>;
 				phy-mode = "qsgmii";
+				buffer-manager = <&bm>;
+				bm,pool-long = <0>;
 			};
 			ethernet@74000 {
 				status = "okay";
 				phy = <&phy1>;
 				phy-mode = "qsgmii";
+				buffer-manager = <&bm>;
+				bm,pool-long = <1>;
 			};
 			ethernet@30000 {
 				status = "okay";
 				phy = <&phy2>;
 				phy-mode = "qsgmii";
+				buffer-manager = <&bm>;
+				bm,pool-long = <2>;
 			};
 			ethernet@34000 {
 				status = "okay";
 				phy = <&phy3>;
 				phy-mode = "qsgmii";
+				buffer-manager = <&bm>;
+				bm,pool-long = <3>;
 			};
 
 			/* Front-side USB slot */
@@ -226,27 +156,72 @@
 				status = "okay";
 			};
 
-			spi0: spi@10600 {
+			bm@c0000 {
 				status = "okay";
-				u-boot,dm-pre-reloc;
-
-				spi-flash@0 {
-					u-boot,dm-pre-reloc;
-					#address-cells = <1>;
-					#size-cells = <1>;
-					compatible = "n25q128a13", "jedec,spi-nor";
-					reg = <0>; /* Chip select 0 */
-					spi-max-frequency = <108000000>;
-				};
 			};
 
 			nand@d0000 {
 				status = "okay";
+				label = "pxa3xx_nand-0";
 				num-cs = <1>;
 				marvell,nand-keep-config;
-				marvell,nand-enable-arbiter;
 				nand-on-flash-bbt;
 			};
 		};
+
+		bm-bppi {
+			status = "okay";
+		};
 	};
 };
+
+&pciec {
+	status = "okay";
+
+	/*
+	 * The 3 slots are physically present as
+	 * standard PCIe slots on the board.
+	 */
+	pcie@1,0 {
+		/* Port 0, Lane 0 */
+		status = "okay";
+	};
+	pcie@9,0 {
+		/* Port 2, Lane 0 */
+		status = "okay";
+	};
+	pcie@a,0 {
+		/* Port 3, Lane 0 */
+		status = "okay";
+	};
+};
+
+&mdio {
+	phy0: ethernet-phy@0 {
+		reg = <16>;
+	};
+
+	phy1: ethernet-phy@1 {
+		reg = <17>;
+	};
+
+	phy2: ethernet-phy@2 {
+		reg = <18>;
+	};
+
+	phy3: ethernet-phy@3 {
+		reg = <19>;
+	};
+};
+
+&spi0 {
+	status = "okay";
+
+	spi-flash@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "n25q128a13", "jedec,spi-nor";
+		reg = <0>; /* Chip select 0 */
+		spi-max-frequency = <108000000>;
+	};
+};
diff --git a/arch/arm/dts/armada-xp-maxbcm.dts b/arch/arm/dts/armada-xp-maxbcm.dts
index d7d7f65..921eb70 100644
--- a/arch/arm/dts/armada-xp-maxbcm.dts
+++ b/arch/arm/dts/armada-xp-maxbcm.dts
@@ -225,18 +225,6 @@
 				status = "okay";
 			};
 
-			spi0: spi@10600 {
-				status = "okay";
-
-				spi-flash@0 {
-					#address-cells = <1>;
-					#size-cells = <1>;
-					compatible = "n25q128a13", "jedec,spi-nor";
-					reg = <0>; /* Chip select 0 */
-					spi-max-frequency = <108000000>;
-				};
-			};
-
 			nand@d0000 {
 				status = "okay";
 				num-cs = <1>;
@@ -247,3 +235,15 @@
 		};
 	};
 };
+
+&spi0 {
+	status = "okay";
+
+	spi-flash@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "n25q128a13", "jedec,spi-nor";
+		reg = <0>; /* Chip select 0 */
+		spi-max-frequency = <108000000>;
+	};
+};
diff --git a/arch/arm/dts/armada-xp-mv78230.dtsi b/arch/arm/dts/armada-xp-mv78230.dtsi
index f6bab9f..8558bf6 100644
--- a/arch/arm/dts/armada-xp-mv78230.dtsi
+++ b/arch/arm/dts/armada-xp-mv78230.dtsi
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Device Tree Include file for Marvell Armada XP family SoC
  *
@@ -5,44 +6,6 @@
  *
  * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
  *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This file is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This file is distributed in the hope that it will be useful
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- * Or, alternatively
- *
- *  b) Permission is hereby granted, free of charge, to any person
- *     obtaining a copy of this software and associated documentation
- *     files (the "Software"), to deal in the Software without
- *     restriction, including without limitation the rights to use
- *     copy, modify, merge, publish, distribute, sublicense, and/or
- *     sell copies of the Software, and to permit persons to whom the
- *     Software is furnished to do so, subject to the following
- *     conditions:
- *
- *     The above copyright notice and this permission notice shall be
- *     included in all copies or substantial portions of the Software.
- *
- *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
- *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
- *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- *     OTHER DEALINGS IN THE SOFTWARE.
- *
  * Contains definitions specific to the Armada XP MV78230 SoC that are not
  * common to all Armada XP SoCs.
  */
@@ -207,25 +170,33 @@
 
 		internal-regs {
 			gpio0: gpio@18100 {
-				compatible = "marvell,orion-gpio";
-				reg = <0x18100 0x40>;
+				compatible = "marvell,armada-370-gpio",
+					     "marvell,orion-gpio";
+				reg = <0x18100 0x40>, <0x181c0 0x08>;
+				reg-names = "gpio", "pwm";
 				ngpios = <32>;
 				gpio-controller;
 				#gpio-cells = <2>;
+				#pwm-cells = <2>;
 				interrupt-controller;
 				#interrupt-cells = <2>;
 				interrupts = <82>, <83>, <84>, <85>;
+				clocks = <&coreclk 0>;
 			};
 
 			gpio1: gpio@18140 {
-				compatible = "marvell,orion-gpio";
-				reg = <0x18140 0x40>;
+				compatible = "marvell,armada-370-gpio",
+					     "marvell,orion-gpio";
+				reg = <0x18140 0x40>, <0x181c8 0x08>;
+				reg-names = "gpio", "pwm";
 				ngpios = <17>;
 				gpio-controller;
 				#gpio-cells = <2>;
+				#pwm-cells = <2>;
 				interrupt-controller;
 				#interrupt-cells = <2>;
 				interrupts = <87>, <88>, <89>;
+				clocks = <&coreclk 0>;
 			};
 		};
 	};
diff --git a/arch/arm/dts/armada-xp-mv78260.dtsi b/arch/arm/dts/armada-xp-mv78260.dtsi
index d39231f..2d85fe8 100644
--- a/arch/arm/dts/armada-xp-mv78260.dtsi
+++ b/arch/arm/dts/armada-xp-mv78260.dtsi
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Device Tree Include file for Marvell Armada XP family SoC
  *
@@ -5,44 +6,6 @@
  *
  * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
  *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This file is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This file is distributed in the hope that it will be useful
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- * Or, alternatively
- *
- *  b) Permission is hereby granted, free of charge, to any person
- *     obtaining a copy of this software and associated documentation
- *     files (the "Software"), to deal in the Software without
- *     restriction, including without limitation the rights to use
- *     copy, modify, merge, publish, distribute, sublicense, and/or
- *     sell copies of the Software, and to permit persons to whom the
- *     Software is furnished to do so, subject to the following
- *     conditions:
- *
- *     The above copyright notice and this permission notice shall be
- *     included in all copies or substantial portions of the Software.
- *
- *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
- *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
- *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- *     OTHER DEALINGS IN THE SOFTWARE.
- *
  * Contains definitions specific to the Armada XP MV78260 SoC that are not
  * common to all Armada XP SoCs.
  */
@@ -294,29 +257,38 @@
 
 		internal-regs {
 			gpio0: gpio@18100 {
-				compatible = "marvell,orion-gpio";
-				reg = <0x18100 0x40>;
+				compatible = "marvell,armada-370-gpio",
+					     "marvell,orion-gpio";
+				reg = <0x18100 0x40>, <0x181c0 0x08>;
+				reg-names = "gpio", "pwm";
 				ngpios = <32>;
 				gpio-controller;
 				#gpio-cells = <2>;
+				#pwm-cells = <2>;
 				interrupt-controller;
 				#interrupt-cells = <2>;
 				interrupts = <82>, <83>, <84>, <85>;
+				clocks = <&coreclk 0>;
 			};
 
 			gpio1: gpio@18140 {
-				compatible = "marvell,orion-gpio";
-				reg = <0x18140 0x40>;
+				compatible = "marvell,armada-370-gpio",
+					     "marvell,orion-gpio";
+				reg = <0x18140 0x40>, <0x181c8 0x08>;
+				reg-names = "gpio", "pwm";
 				ngpios = <32>;
 				gpio-controller;
 				#gpio-cells = <2>;
+				#pwm-cells = <2>;
 				interrupt-controller;
 				#interrupt-cells = <2>;
 				interrupts = <87>, <88>, <89>, <90>;
+				clocks = <&coreclk 0>;
 			};
 
 			gpio2: gpio@18180 {
-				compatible = "marvell,orion-gpio";
+				compatible = "marvell,armada-370-gpio",
+					     "marvell,orion-gpio";
 				reg = <0x18180 0x40>;
 				ngpios = <3>;
 				gpio-controller;
diff --git a/arch/arm/dts/armada-xp-mv78460.dtsi b/arch/arm/dts/armada-xp-mv78460.dtsi
index c642565..230a3fd 100644
--- a/arch/arm/dts/armada-xp-mv78460.dtsi
+++ b/arch/arm/dts/armada-xp-mv78460.dtsi
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Device Tree Include file for Marvell Armada XP family SoC
  *
@@ -5,44 +6,6 @@
  *
  * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
  *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This file is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This file is distributed in the hope that it will be useful
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- * Or, alternatively
- *
- *  b) Permission is hereby granted, free of charge, to any person
- *     obtaining a copy of this software and associated documentation
- *     files (the "Software"), to deal in the Software without
- *     restriction, including without limitation the rights to use
- *     copy, modify, merge, publish, distribute, sublicense, and/or
- *     sell copies of the Software, and to permit persons to whom the
- *     Software is furnished to do so, subject to the following
- *     conditions:
- *
- *     The above copyright notice and this permission notice shall be
- *     included in all copies or substantial portions of the Software.
- *
- *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
- *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
- *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- *     OTHER DEALINGS IN THE SOFTWARE.
- *
  * Contains definitions specific to the Armada XP MV78460 SoC that are not
  * common to all Armada XP SoCs.
  */
@@ -333,29 +296,38 @@
 
 		internal-regs {
 			gpio0: gpio@18100 {
-				compatible = "marvell,orion-gpio";
-				reg = <0x18100 0x40>;
+				compatible = "marvell,armada-370-gpio",
+					     "marvell,orion-gpio";
+				reg = <0x18100 0x40>, <0x181c0 0x08>;
+				reg-names = "gpio", "pwm";
 				ngpios = <32>;
 				gpio-controller;
 				#gpio-cells = <2>;
+				#pwm-cells = <2>;
 				interrupt-controller;
 				#interrupt-cells = <2>;
 				interrupts = <82>, <83>, <84>, <85>;
+				clocks = <&coreclk 0>;
 			};
 
 			gpio1: gpio@18140 {
-				compatible = "marvell,orion-gpio";
-				reg = <0x18140 0x40>;
+				compatible = "marvell,armada-370-gpio",
+					     "marvell,orion-gpio";
+				reg = <0x18140 0x40>, <0x181c8 0x08>;
+				reg-names = "gpio", "pwm";
 				ngpios = <32>;
 				gpio-controller;
 				#gpio-cells = <2>;
+				#pwm-cells = <2>;
 				interrupt-controller;
 				#interrupt-cells = <2>;
 				interrupts = <87>, <88>, <89>, <90>;
+				clocks = <&coreclk 0>;
 			};
 
 			gpio2: gpio@18180 {
-				compatible = "marvell,orion-gpio";
+				compatible = "marvell,armada-370-gpio",
+					     "marvell,orion-gpio";
 				reg = <0x18180 0x40>;
 				ngpios = <3>;
 				gpio-controller;
diff --git a/arch/arm/dts/armada-xp-synology-ds414.dts b/arch/arm/dts/armada-xp-synology-ds414.dts
index 0a60ddf..861967c 100644
--- a/arch/arm/dts/armada-xp-synology-ds414.dts
+++ b/arch/arm/dts/armada-xp-synology-ds414.dts
@@ -1,13 +1,9 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Device Tree file for Synology DS414
  *
  * Copyright (C) 2014, Arnaud EBALARD <arno@natisbad.org>
  *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- *
  * Note: this Device Tree assumes that the bootloader has remapped the
  * internal registers to 0xf1000000 (instead of the old 0xd0000000).
  * The 0xf1000000 is the default used by the recent, DT-capable, U-Boot
@@ -42,36 +38,16 @@
 		spi0 = &spi0;
 	};
 
-	memory {
+	memory@0 {
 		device_type = "memory";
 		reg = <0 0x00000000 0 0x40000000>; /* 1GB */
 	};
 
 	soc {
 		ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xf1000000 0x100000
-			  MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000>;
-
-		pcie-controller {
-			status = "okay";
-
-			/*
-			 * Connected to Marvell 88SX7042 SATA-II controller
-			 * handling the four disks.
-			 */
-			pcie@1,0 {
-				/* Port 0, Lane 0 */
-				status = "okay";
-			};
-
-			/*
-			 * Connected to EtronTech EJ168A XHCI controller
-			 * providing the two rear USB 3.0 ports.
-			 */
-			pcie@5,0 {
-				/* Port 1, Lane 0 */
-				status = "okay";
-			};
-		};
+			  MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000
+			  MBUS_ID(0x09, 0x09) 0 0 0xf1100000 0x10000
+			  MBUS_ID(0x09, 0x05) 0 0 0xf1110000 0x10000>;
 
 		internal-regs {
 
@@ -80,64 +56,6 @@
 				status = "disabled";
 			};
 
-			spi0: spi@10600 {
-				status = "okay";
-				u-boot,dm-pre-reloc;
-
-				spi-flash@0 {
-					u-boot,dm-pre-reloc;
-					#address-cells = <1>;
-					#size-cells = <1>;
-					compatible = "micron,n25q064";
-					reg = <0>; /* Chip select 0 */
-					spi-max-frequency = <20000000>;
-
-					/*
-					 * Warning!
-					 *
-					 * Synology u-boot uses its compiled-in environment
-					 * and it seems Synology did not care to change u-boot
-					 * default configuration in order to allow saving a
-					 * modified environment at a sensible location. So,
-					 * if you do a 'saveenv' under u-boot, your modified
-					 * environment will be saved at 1MB after the start
-					 * of the flash, i.e. in the middle of the uImage.
-					 * For that reason, it is strongly advised not to
-					 * change the default environment, unless you know
-					 * what you are doing.
-					 */
-					partition@00000000 { /* u-boot */
-						label = "RedBoot";
-						reg = <0x00000000 0x000d0000>; /* 832KB */
-					};
-
-					partition@000c0000 { /* uImage */
-						label = "zImage";
-						reg = <0x000d0000 0x002d0000>; /* 2880KB */
-					};
-
-					partition@003a0000 { /* uInitramfs */
-						label = "rd.gz";
-						reg = <0x003a0000 0x00430000>; /* 4250KB */
-					};
-
-					partition@007d0000 { /* MAC address and serial number */
-						label = "vendor";
-						reg = <0x007d0000 0x00010000>; /* 64KB */
-					};
-
-					partition@007e0000 {
-						label = "RedBoot config";
-						reg = <0x007e0000 0x00010000>; /* 64KB */
-					};
-
-					partition@007f0000 {
-						label = "FIS directory";
-						reg = <0x007f0000 0x00010000>; /* 64KB */
-					};
-				};
-			};
-
 			i2c@11000 {
 				clock-frequency = <400000>;
 				status = "okay";
@@ -179,16 +97,6 @@
 				status = "okay";
 			};
 
-			mdio {
-				phy0: ethernet-phy@0 { /* Marvell 88E1512 */
-					reg = <0>;
-				};
-
-				phy1: ethernet-phy@1 { /* Marvell 88E1512 */
-					reg = <1>;
-				};
-			};
-
 			ethernet@70000 {
 				status = "okay";
 				pinctrl-0 = <&ge0_rgmii_pins>;
@@ -215,7 +123,7 @@
 			     &sata3_pwr_pin &sata4_pwr_pin>;
 		pinctrl-names = "default";
 
-		sata1_regulator: sata1-regulator {
+		sata1_regulator: sata1-regulator@1 {
 			compatible = "regulator-fixed";
 			reg = <1>;
 			regulator-name = "SATA1 Power";
@@ -228,7 +136,7 @@
 			gpio = <&gpio1 10 GPIO_ACTIVE_HIGH>;
 		};
 
-		sata2_regulator: sata2-regulator {
+		sata2_regulator: sata2-regulator@2 {
 			compatible = "regulator-fixed";
 			reg = <2>;
 			regulator-name = "SATA2 Power";
@@ -241,7 +149,7 @@
 			gpio = <&gpio1 12 GPIO_ACTIVE_HIGH>;
 		};
 
-		sata3_regulator: sata3-regulator {
+		sata3_regulator: sata3-regulator@3 {
 			compatible = "regulator-fixed";
 			reg = <3>;
 			regulator-name = "SATA3 Power";
@@ -254,7 +162,7 @@
 			gpio = <&gpio1 13 GPIO_ACTIVE_HIGH>;
 		};
 
-		sata4_regulator: sata4-regulator {
+		sata4_regulator: sata4-regulator@4 {
 			compatible = "regulator-fixed";
 			reg = <4>;
 			regulator-name = "SATA4 Power";
@@ -269,6 +177,39 @@
 	};
 };
 
+&pciec {
+	status = "okay";
+
+	/*
+	 * Connected to Marvell 88SX7042 SATA-II controller
+	 * handling the four disks.
+	 */
+	pcie@1,0 {
+		/* Port 0, Lane 0 */
+		status = "okay";
+	};
+
+	/*
+	 * Connected to EtronTech EJ168A XHCI controller
+	 * providing the two rear USB 3.0 ports.
+	 */
+	pcie@5,0 {
+		/* Port 1, Lane 0 */
+		status = "okay";
+	};
+};
+
+
+&mdio {
+	phy0: ethernet-phy@0 { /* Marvell 88E1512 */
+		reg = <0>;
+	};
+
+	phy1: ethernet-phy@1 { /* Marvell 88E1512 */
+		reg = <1>;
+	};
+};
+
 &pinctrl {
 	sata1_pwr_pin: sata1-pwr-pin {
 		marvell,pins = "mpp42";
@@ -335,3 +276,59 @@
 		marvell,function = "gpio";
 	};
 };
+
+&spi0 {
+	status = "okay";
+
+	spi-flash@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "micron,n25q064", "jedec,spi-nor";
+		reg = <0>; /* Chip select 0 */
+		spi-max-frequency = <20000000>;
+
+		/*
+		 * Warning!
+		 *
+		 * Synology u-boot uses its compiled-in environment
+		 * and it seems Synology did not care to change u-boot
+		 * default configuration in order to allow saving a
+		 * modified environment at a sensible location. So,
+		 * if you do a 'saveenv' under u-boot, your modified
+		 * environment will be saved at 1MB after the start
+		 * of the flash, i.e. in the middle of the uImage.
+		 * For that reason, it is strongly advised not to
+		 * change the default environment, unless you know
+		 * what you are doing.
+		 */
+		partition@0 { /* u-boot */
+			label = "RedBoot";
+			reg = <0x00000000 0x000d0000>; /* 832KB */
+		};
+
+		partition@c0000 { /* uImage */
+			label = "zImage";
+			reg = <0x000d0000 0x002d0000>; /* 2880KB */
+		};
+
+		partition@3a0000 { /* uInitramfs */
+			label = "rd.gz";
+			reg = <0x003a0000 0x00430000>; /* 4250KB */
+		};
+
+		partition@7d0000 { /* MAC address and serial number */
+			label = "vendor";
+			reg = <0x007d0000 0x00010000>; /* 64KB */
+		};
+
+		partition@7e0000 {
+			label = "RedBoot config";
+			reg = <0x007e0000 0x00010000>; /* 64KB */
+		};
+
+		partition@7f0000 {
+			label = "FIS directory";
+			reg = <0x007f0000 0x00010000>; /* 64KB */
+		};
+	};
+};
diff --git a/arch/arm/dts/armada-xp-theadorable.dts b/arch/arm/dts/armada-xp-theadorable.dts
index 5695e9b..5b18d62 100644
--- a/arch/arm/dts/armada-xp-theadorable.dts
+++ b/arch/arm/dts/armada-xp-theadorable.dts
@@ -126,40 +126,6 @@
 				status = "okay";
 			};
 
-			spi0: spi@10600 {
-				status = "okay";
-				u-boot,dm-pre-reloc;
-
-				spi-flash@0 {
-					u-boot,dm-pre-reloc;
-					#address-cells = <1>;
-					#size-cells = <1>;
-					compatible = "n25q128a13", "jedec,spi-nor", "spi-flash";
-					reg = <0>; /* Chip select 0 */
-					spi-max-frequency = <27777777>;
-				};
-
-				fpga@1 {
-					#address-cells = <1>;
-					#size-cells = <1>;
-					compatible = "spi-generic-device";
-					reg = <1>; /* Chip select 1 */
-					spi-max-frequency = <27777777>;
-				};
-			};
-
-			spi1: spi@10680 {
-				status = "okay";
-
-				fpga@0 {
-					#address-cells = <1>;
-					#size-cells = <1>;
-					compatible = "spi-generic-device";
-					reg = <0>; /* Chip select 0 */
-					spi-max-frequency = <27777777>;
-				};
-			};
-
 			/* The LCD controller is only used on this board */
 			lcd0: lcd-controller@e0000 {
 				compatible = "marvell,armada-xp-lcd";
@@ -188,6 +154,41 @@
 	};
 };
 
+&spi0 {
+	status = "okay";
+	u-boot,dm-pre-reloc;
+
+	spi-flash@0 {
+		u-boot,dm-pre-reloc;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "n25q128a13", "jedec,spi-nor";
+		reg = <0>; /* Chip select 0 */
+		spi-max-frequency = <27777777>;
+	};
+
+	fpga@1 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "spi-generic-device";
+		reg = <1>; /* Chip select 1 */
+		spi-max-frequency = <27777777>;
+	};
+};
+
+&spi1 {
+	status = "okay";
+
+	fpga@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "spi-generic-device";
+		reg = <0>; /* Chip select 0 */
+		spi-max-frequency = <27777777>;
+	};
+};
+
+
 &pciec {
 	status = "okay";
 
diff --git a/arch/arm/dts/armada-xp.dtsi b/arch/arm/dts/armada-xp.dtsi
index 3fac39e..d856d96 100644
--- a/arch/arm/dts/armada-xp.dtsi
+++ b/arch/arm/dts/armada-xp.dtsi
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Device Tree Include file for Marvell Armada XP family SoC
  *
@@ -8,44 +9,6 @@
  * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
  * Ben Dooks <ben.dooks@codethink.co.uk>
  *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This file is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This file is distributed in the hope that it will be useful
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- * Or, alternatively
- *
- *  b) Permission is hereby granted, free of charge, to any person
- *     obtaining a copy of this software and associated documentation
- *     files (the "Software"), to deal in the Software without
- *     restriction, including without limitation the rights to use
- *     copy, modify, merge, publish, distribute, sublicense, and/or
- *     sell copies of the Software, and to permit persons to whom the
- *     Software is furnished to do so, subject to the following
- *     conditions:
- *
- *     The above copyright notice and this permission notice shall be
- *     included in all copies or substantial portions of the Software.
- *
- *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
- *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
- *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- *     OTHER DEALINGS IN THE SOFTWARE.
- *
  * Contains definitions specific to the Armada XP SoC that are not
  * common to all Armada SoCs.
  */
@@ -53,6 +16,9 @@
 #include "armada-370-xp.dtsi"
 
 / {
+	#address-cells = <2>;
+	#size-cells = <2>;
+
 	model = "Marvell Armada XP family SoC";
 	compatible = "marvell,armadaxp", "marvell,armada-370-xp";
 
@@ -71,12 +37,12 @@
 		};
 
 		internal-regs {
-			sdramc@1400 {
+			sdramc: sdramc@1400 {
 				compatible = "marvell,armada-xp-sdram-controller";
 				reg = <0x1400 0x500>;
 			};
 
-			L2: l2-cache {
+			L2: l2-cache@8000 {
 				compatible = "marvell,aurora-system-cache";
 				reg = <0x08000 0x1000>;
 				cache-id-part = <0x100>;
@@ -85,29 +51,6 @@
 				wt-override;
 			};
 
-			spi0: spi@10600 {
-				compatible = "marvell,armada-xp-spi",
-						"marvell,orion-spi";
-				pinctrl-0 = <&spi0_pins>;
-				pinctrl-names = "default";
-			};
-
-			spi1: spi@10680 {
-				compatible = "marvell,armada-xp-spi",
-						"marvell,orion-spi";
-			};
-
-
-			i2c0: i2c@11000 {
-				compatible = "marvell,mv78230-i2c", "marvell,mv64xxx-i2c";
-				reg = <0x11000 0x100>;
-			};
-
-			i2c1: i2c@11100 {
-				compatible = "marvell,mv78230-i2c", "marvell,mv64xxx-i2c";
-				reg = <0x11100 0x100>;
-			};
-
 			uart2: serial@12200 {
 				compatible = "snps,dw-apb-uart";
 				pinctrl-0 = <&uart2_pins>;
@@ -132,7 +75,7 @@
 				status = "disabled";
 			};
 
-			system-controller@18200 {
+			systemc: system-controller@18200 {
 				compatible = "marvell,armada-370-xp-system-controller";
 				reg = <0x18200 0x500>;
 			};
@@ -150,7 +93,7 @@
 				#clock-cells = <1>;
 			};
 
-			thermal@182b0 {
+			thermal: thermal@182b0 {
 				compatible = "marvell,armadaxp-thermal";
 				reg = <0x182b0 0x4
 					0x184d0 0x4>;
@@ -164,27 +107,11 @@
 				clocks = <&coreclk 1>;
 			};
 
-			interrupt-controller@20a00 {
-			      reg = <0x20a00 0x2d0>, <0x21070 0x58>;
-			};
-
-			timer@20300 {
-				compatible = "marvell,armada-xp-timer";
-				clocks = <&coreclk 2>, <&refclk>;
-				clock-names = "nbclk", "fixed";
+			cpu-config@21000 {
+				compatible = "marvell,armada-xp-cpu-config";
+				reg = <0x21000 0x8>;
 			};
 
-			watchdog@20300 {
-				compatible = "marvell,armada-xp-wdt";
-				clocks = <&coreclk 2>, <&refclk>;
-				clock-names = "nbclk", "fixed";
-			};
-
-			cpurst@20800 {
-				compatible = "marvell,armada-370-cpu-reset";
-				reg = <0x20800 0x20>;
-			};
-
 			eth2: ethernet@30000 {
 				compatible = "marvell,armada-xp-neta";
 				reg = <0x30000 0x4000>;
@@ -193,15 +120,7 @@
 				status = "disabled";
 			};
 
-			usb@50000 {
-				clocks = <&gateclk 18>;
-			};
-
-			usb@51000 {
-				clocks = <&gateclk 19>;
-			};
-
-			usb@52000 {
+			usb2: usb@52000 {
 				compatible = "marvell,orion-ehci";
 				reg = <0x52000 0x500>;
 				interrupts = <47>;
@@ -209,7 +128,7 @@
 				status = "disabled";
 			};
 
-			xor@60900 {
+			xor1: xor@60900 {
 				compatible = "marvell,orion-xor";
 				reg = <0x60900 0x100
 				       0x60b00 0x100>;
@@ -237,7 +156,27 @@
 				compatible = "marvell,armada-xp-neta";
 			};
 
-			xor@f0900 {
+			cesa: crypto@90000 {
+				compatible = "marvell,armada-xp-crypto";
+				reg = <0x90000 0x10000>;
+				reg-names = "regs";
+				interrupts = <48>, <49>;
+				clocks = <&gateclk 23>, <&gateclk 23>;
+				clock-names = "cesa0", "cesa1";
+				marvell,crypto-srams = <&crypto_sram0>,
+						       <&crypto_sram1>;
+				marvell,crypto-sram-size = <0x800>;
+			};
+
+			bm: bm@c0000 {
+				compatible = "marvell,armada-380-neta-bm";
+				reg = <0xc0000 0xac>;
+				clocks = <&gateclk 13>;
+				internal-mem = <&bm_bppi>;
+				status = "disabled";
+			};
+
+			xor0: xor@f0900 {
 				compatible = "marvell,orion-xor";
 				reg = <0xF0900 0x100
 				       0xF0B00 0x100>;
@@ -257,6 +196,35 @@
 				};
 			};
 		};
+
+		crypto_sram0: sa-sram0 {
+			compatible = "mmio-sram";
+			reg = <MBUS_ID(0x09, 0x09) 0 0x800>;
+			clocks = <&gateclk 23>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 MBUS_ID(0x09, 0x09) 0 0x800>;
+		};
+
+		crypto_sram1: sa-sram1 {
+			compatible = "mmio-sram";
+			reg = <MBUS_ID(0x09, 0x05) 0 0x800>;
+			clocks = <&gateclk 23>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 MBUS_ID(0x09, 0x05) 0 0x800>;
+		};
+
+		bm_bppi: bm-bppi {
+			compatible = "mmio-sram";
+			reg = <MBUS_ID(0x0c, 0x04) 0 0x100000>;
+			ranges = <0 MBUS_ID(0x0c, 0x04) 0 0x100000>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			clocks = <&gateclk 13>;
+			no-memory-wc;
+			status = "disabled";
+		};
 	};
 
 	clocks {
@@ -269,6 +237,44 @@
 	};
 };
 
+&i2c0 {
+	compatible = "marvell,mv78230-i2c", "marvell,mv64xxx-i2c";
+	reg = <0x11000 0x100>;
+};
+
+&i2c1 {
+	compatible = "marvell,mv78230-i2c", "marvell,mv64xxx-i2c";
+	reg = <0x11100 0x100>;
+};
+
+&mpic {
+	reg = <0x20a00 0x2d0>, <0x21070 0x58>;
+};
+
+&timer {
+	compatible = "marvell,armada-xp-timer";
+	clocks = <&coreclk 2>, <&refclk>;
+	clock-names = "nbclk", "fixed";
+};
+
+&watchdog {
+	compatible = "marvell,armada-xp-wdt";
+	clocks = <&coreclk 2>, <&refclk>;
+	clock-names = "nbclk", "fixed";
+};
+
+&cpurst {
+	reg = <0x20800 0x20>;
+};
+
+&usb0 {
+	clocks = <&gateclk 18>;
+};
+
+&usb1 {
+	clocks = <&gateclk 19>;
+};
+
 &pinctrl {
 	ge0_gmii_pins: ge0-gmii-pins {
 		marvell,pins =
@@ -309,6 +315,12 @@
 		marvell,function = "spi0";
 	};
 
+	spi1_pins: spi1-pins {
+		marvell,pins = "mpp13", "mpp14",
+			       "mpp16", "mpp17";
+		marvell,function = "spi1";
+	};
+
 	uart2_pins: uart2-pins {
 		marvell,pins = "mpp42", "mpp43";
 		marvell,function = "uart2";
@@ -319,3 +331,15 @@
 		marvell,function = "uart3";
 	};
 };
+
+&spi0 {
+	compatible = "marvell,armada-xp-spi", "marvell,orion-spi";
+	pinctrl-0 = <&spi0_pins>;
+	pinctrl-names = "default";
+};
+
+&spi1 {
+	compatible = "marvell,armada-xp-spi", "marvell,orion-spi";
+	pinctrl-0 = <&spi1_pins>;
+	pinctrl-names = "default";
+};
diff --git a/arch/arm/dts/at91-sama5d2_xplained.dts b/arch/arm/dts/at91-sama5d2_xplained.dts
index 33064b3..c0708fe 100644
--- a/arch/arm/dts/at91-sama5d2_xplained.dts
+++ b/arch/arm/dts/at91-sama5d2_xplained.dts
@@ -110,7 +110,7 @@
 				u-boot,dm-pre-reloc;
 
 				spi_flash@0 {
-					compatible = "spi-flash";
+					compatible = "jedec,spi-nor";
 					reg = <0>;
 					spi-max-frequency = <50000000>;
 					u-boot,dm-pre-reloc;
diff --git a/arch/arm/dts/at91-sama5d4_xplained.dts b/arch/arm/dts/at91-sama5d4_xplained.dts
index 58a0e60..7da5086 100644
--- a/arch/arm/dts/at91-sama5d4_xplained.dts
+++ b/arch/arm/dts/at91-sama5d4_xplained.dts
@@ -117,7 +117,7 @@
 				status = "okay";
 				spi_flash@0 {
 					u-boot,dm-pre-reloc;
-					compatible = "spi-flash";
+					compatible = "jedec,spi-nor";
 					spi-max-frequency = <50000000>;
 					reg = <0>;
 				};
diff --git a/arch/arm/dts/at91-sama5d4ek.dts b/arch/arm/dts/at91-sama5d4ek.dts
index a5d7545..c1d6578 100644
--- a/arch/arm/dts/at91-sama5d4ek.dts
+++ b/arch/arm/dts/at91-sama5d4ek.dts
@@ -137,7 +137,7 @@
 				status = "okay";
 				spi_flash@0 {
 					u-boot,dm-pre-reloc;
-					compatible = "spi-flash";
+					compatible = "jedec,spi-nor";
 					spi-max-frequency = <50000000>;
 					reg = <0>;
 				};
diff --git a/arch/arm/dts/at91sam9n12ek.dts b/arch/arm/dts/at91sam9n12ek.dts
index 888bda1..64a7abf 100644
--- a/arch/arm/dts/at91sam9n12ek.dts
+++ b/arch/arm/dts/at91sam9n12ek.dts
@@ -112,7 +112,7 @@
 				status = "okay";
 				cs-gpios = <&pioA 14 0>, <0>, <0>, <0>;
 				spi_flash@0 {
-					compatible = "spi-flash";
+					compatible = "jedec,spi-nor";
 					spi-max-frequency = <50000000>;
 					reg = <0>;
 				};
diff --git a/arch/arm/dts/at91sam9x5ek.dtsi b/arch/arm/dts/at91sam9x5ek.dtsi
index f2a532d..1f7f37b 100644
--- a/arch/arm/dts/at91sam9x5ek.dtsi
+++ b/arch/arm/dts/at91sam9x5ek.dtsi
@@ -121,7 +121,7 @@
 				status = "okay";
 				cs-gpios = <&pioA 14 0>, <0>, <0>, <0>;
 				spi_flash@0 {
-					compatible = "spi-flash";
+					compatible = "jedec,spi-nor";
 					spi-max-frequency = <50000000>;
 					reg = <0>;
 				};
diff --git a/arch/arm/dts/bcm63158.dtsi b/arch/arm/dts/bcm63158.dtsi
index 6a3fbc9..4f41f62 100644
--- a/arch/arm/dts/bcm63158.dtsi
+++ b/arch/arm/dts/bcm63158.dtsi
@@ -98,5 +98,85 @@
 			compatible = "wdt-reboot";
 			wdt = <&wdt1>;
 		};
+
+		gpio0: gpio-controller@0xff800500 {
+			compatible = "brcm,bcm6345-gpio";
+			reg = <0x0 0xff800500 0x0 0x4>,
+			      <0x0 0xff800520 0x0 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			status = "disabled";
+		};
+
+		gpio1: gpio-controller@0xff800504 {
+			compatible = "brcm,bcm6345-gpio";
+			reg = <0x0 0xff800504 0x0 0x4>,
+			      <0x0 0xff800524 0x0 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			status = "disabled";
+		};
+
+		gpio2: gpio-controller@0xff800508 {
+			compatible = "brcm,bcm6345-gpio";
+			reg = <0x0 0xff800508 0x0 0x4>,
+			      <0x0 0xff800528 0x0 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			status = "disabled";
+		};
+
+		gpio3: gpio-controller@0xff80050c {
+			compatible = "brcm,bcm6345-gpio";
+			reg = <0x0 0xff80050c 0x0 0x4>,
+			      <0x0 0xff80052c 0x0 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			status = "disabled";
+		};
+
+		gpio4: gpio-controller@0xff800510 {
+			compatible = "brcm,bcm6345-gpio";
+			reg = <0x0 0xff800510 0x0 0x4>,
+			      <0x0 0xff800530 0x0 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			status = "disabled";
+		};
+
+		gpio5: gpio-controller@0xff800514 {
+			compatible = "brcm,bcm6345-gpio";
+			reg = <0x0 0xff800514 0x0 0x4>,
+			      <0x0 0xff800534 0x0 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			status = "disabled";
+		};
+
+		gpio6: gpio-controller@0xff800518 {
+			compatible = "brcm,bcm6345-gpio";
+			reg = <0x0 0xff800518 0x0 0x4>,
+			      <0x0 0xff800538 0x0 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			status = "disabled";
+		};
+
+		gpio7: gpio-controller@0xff80051c {
+			compatible = "brcm,bcm6345-gpio";
+			reg = <0x0 0xff80051c 0x0 0x4>,
+			      <0x0 0xff80053c 0x0 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			status = "disabled";
+		};
 	};
 };
diff --git a/arch/arm/dts/bcm6858.dtsi b/arch/arm/dts/bcm6858.dtsi
index 23b80c6..5d5e64d 100644
--- a/arch/arm/dts/bcm6858.dtsi
+++ b/arch/arm/dts/bcm6858.dtsi
@@ -98,5 +98,85 @@
 			compatible = "wdt-reboot";
 			wdt = <&wdt1>;
 		};
+
+		gpio0: gpio-controller@0xff800500 {
+			compatible = "brcm,bcm6345-gpio";
+			reg = <0x0 0xff800500 0x0 0x4>,
+			      <0x0 0xff800520 0x0 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			status = "disabled";
+		};
+
+		gpio1: gpio-controller@0xff800504 {
+			compatible = "brcm,bcm6345-gpio";
+			reg = <0x0 0xff800504 0x0 0x4>,
+			      <0x0 0xff800524 0x0 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			status = "disabled";
+		};
+
+		gpio2: gpio-controller@0xff800508 {
+			compatible = "brcm,bcm6345-gpio";
+			reg = <0x0 0xff800508 0x0 0x4>,
+			      <0x0 0xff800528 0x0 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			status = "disabled";
+		};
+
+		gpio3: gpio-controller@0xff80050c {
+			compatible = "brcm,bcm6345-gpio";
+			reg = <0x0 0xff80050c 0x0 0x4>,
+			      <0x0 0xff80052c 0x0 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			status = "disabled";
+		};
+
+		gpio4: gpio-controller@0xff800510 {
+			compatible = "brcm,bcm6345-gpio";
+			reg = <0x0 0xff800510 0x0 0x4>,
+			      <0x0 0xff800530 0x0 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			status = "disabled";
+		};
+
+		gpio5: gpio-controller@0xff800514 {
+			compatible = "brcm,bcm6345-gpio";
+			reg = <0x0 0xff800514 0x0 0x4>,
+			      <0x0 0xff800534 0x0 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			status = "disabled";
+		};
+
+		gpio6: gpio-controller@0xff800518 {
+			compatible = "brcm,bcm6345-gpio";
+			reg = <0x0 0xff800518 0x0 0x4>,
+			      <0x0 0xff800538 0x0 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			status = "disabled";
+		};
+
+		gpio7: gpio-controller@0xff80051c {
+			compatible = "brcm,bcm6345-gpio";
+			reg = <0x0 0xff80051c 0x0 0x4>,
+			      <0x0 0xff80053c 0x0 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			status = "disabled";
+		};
 	};
 };
diff --git a/arch/arm/dts/bcm963158.dts b/arch/arm/dts/bcm963158.dts
index dc5afb5..b5c825b 100644
--- a/arch/arm/dts/bcm963158.dts
+++ b/arch/arm/dts/bcm963158.dts
@@ -29,3 +29,35 @@
 	u-boot,dm-pre-reloc;
 	status = "okay";
 };
+
+&gpio0 {
+	status = "okay";
+};
+
+&gpio1 {
+	status = "okay";
+};
+
+&gpio2 {
+	status = "okay";
+};
+
+&gpio3 {
+	status = "okay";
+};
+
+&gpio4 {
+	status = "okay";
+};
+
+&gpio5 {
+	status = "okay";
+};
+
+&gpio6 {
+	status = "okay";
+};
+
+&gpio7 {
+	status = "okay";
+};
diff --git a/arch/arm/dts/bcm968580xref.dts b/arch/arm/dts/bcm968580xref.dts
index 0c59f94..15febb0 100644
--- a/arch/arm/dts/bcm968580xref.dts
+++ b/arch/arm/dts/bcm968580xref.dts
@@ -29,3 +29,35 @@
 	u-boot,dm-pre-reloc;
 	status = "okay";
 };
+
+&gpio0 {
+	status = "okay";
+};
+
+&gpio1 {
+	status = "okay";
+};
+
+&gpio2 {
+	status = "okay";
+};
+
+&gpio3 {
+	status = "okay";
+};
+
+&gpio4 {
+	status = "okay";
+};
+
+&gpio5 {
+	status = "okay";
+};
+
+&gpio6 {
+	status = "okay";
+};
+
+&gpio7 {
+	status = "okay";
+};
diff --git a/arch/arm/dts/bk4r1.dts b/arch/arm/dts/bk4r1.dts
index 866b80e..16c6026 100644
--- a/arch/arm/dts/bk4r1.dts
+++ b/arch/arm/dts/bk4r1.dts
@@ -32,7 +32,7 @@
 	qflash0: spi_flash@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <108000000>;
 		reg = <0>;
 	};
@@ -40,7 +40,7 @@
 	qflash1: spi_flash@1 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <66000000>;
 		reg = <1>;
 	};
diff --git a/arch/arm/dts/da850-evm-u-boot.dtsi b/arch/arm/dts/da850-evm-u-boot.dtsi
index ab9368b..1683f34 100644
--- a/arch/arm/dts/da850-evm-u-boot.dtsi
+++ b/arch/arm/dts/da850-evm-u-boot.dtsi
@@ -13,7 +13,7 @@
 };
 
 &flash {
-	compatible = "m25p64", "spi-flash";
+	compatible = "m25p64", "jedec,spi-nor";
 };
 
 &mmc0 {
diff --git a/arch/arm/dts/exynos5250-snow.dts b/arch/arm/dts/exynos5250-snow.dts
index 7587dc0..e41f2d3 100644
--- a/arch/arm/dts/exynos5250-snow.dts
+++ b/arch/arm/dts/exynos5250-snow.dts
@@ -232,7 +232,7 @@
 	spi@12d30000 {
 		spi-max-frequency = <50000000>;
 		firmware_storage_spi: flash@0 {
-			compatible = "spi-flash";
+			compatible = "jedec,spi-nor";
 			reg = <0>;
 		};
 	};
diff --git a/arch/arm/dts/exynos5250-spring.dts b/arch/arm/dts/exynos5250-spring.dts
index c755320..77e7a6b 100644
--- a/arch/arm/dts/exynos5250-spring.dts
+++ b/arch/arm/dts/exynos5250-spring.dts
@@ -149,7 +149,7 @@
 	spi@12d30000 {
 		spi-max-frequency = <50000000>;
 		firmware_storage_spi: flash@0 {
-			compatible = "spi-flash";
+			compatible = "jedec,spi-nor";
 			reg = <0>;
 		};
 	};
diff --git a/arch/arm/dts/exynos5420-peach-pit.dts b/arch/arm/dts/exynos5420-peach-pit.dts
index 4a96a18..a68c3b5 100644
--- a/arch/arm/dts/exynos5420-peach-pit.dts
+++ b/arch/arm/dts/exynos5420-peach-pit.dts
@@ -257,7 +257,7 @@
 	spi@12d30000 { /* spi1 */
 		spi-max-frequency = <50000000>;
 		firmware_storage_spi: flash@0 {
-			compatible = "spi-flash";
+			compatible = "jedec,spi-nor";
 			reg = <0>;
 
 			/*
diff --git a/arch/arm/dts/fsl-ls1012a-2g5rdb.dts b/arch/arm/dts/fsl-ls1012a-2g5rdb.dts
index cdd4ce4..fecef88 100644
--- a/arch/arm/dts/fsl-ls1012a-2g5rdb.dts
+++ b/arch/arm/dts/fsl-ls1012a-2g5rdb.dts
@@ -27,7 +27,7 @@
 	qflash0: s25fl128s@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <20000000>;
 		reg = <0>;
 	};
diff --git a/arch/arm/dts/fsl-ls1012a-frdm.dtsi b/arch/arm/dts/fsl-ls1012a-frdm.dtsi
index 9cb3de1..a357793 100644
--- a/arch/arm/dts/fsl-ls1012a-frdm.dtsi
+++ b/arch/arm/dts/fsl-ls1012a-frdm.dtsi
@@ -21,7 +21,7 @@
 	qflash0: s25fl128s@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <20000000>;
 		reg = <0>;
 	};
diff --git a/arch/arm/dts/fsl-ls1012a-frwy.dts b/arch/arm/dts/fsl-ls1012a-frwy.dts
index a56909a..7242af5 100644
--- a/arch/arm/dts/fsl-ls1012a-frwy.dts
+++ b/arch/arm/dts/fsl-ls1012a-frwy.dts
@@ -28,7 +28,7 @@
 	qflash0: w25q16dw@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <20000000>;
 		reg = <0>;
 	};
diff --git a/arch/arm/dts/fsl-ls1012a-qds.dtsi b/arch/arm/dts/fsl-ls1012a-qds.dtsi
index 661af0e..a330597 100644
--- a/arch/arm/dts/fsl-ls1012a-qds.dtsi
+++ b/arch/arm/dts/fsl-ls1012a-qds.dtsi
@@ -20,7 +20,7 @@
 	dflash0: n25q128a {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		reg = <0>;
 		spi-max-frequency = <1000000>; /* input clock */
 	};
@@ -28,7 +28,7 @@
 	dflash1: sst25wf040b {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <3500000>;
 		reg = <1>;
 	};
@@ -36,7 +36,7 @@
 	dflash2: en25s64 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <3500000>;
 		reg = <2>;
 	};
@@ -49,7 +49,7 @@
 	qflash0: s25fl128s@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <20000000>;
 		reg = <0>;
 	};
diff --git a/arch/arm/dts/fsl-ls1012a-rdb.dtsi b/arch/arm/dts/fsl-ls1012a-rdb.dtsi
index 757e2eb..f053e78 100644
--- a/arch/arm/dts/fsl-ls1012a-rdb.dtsi
+++ b/arch/arm/dts/fsl-ls1012a-rdb.dtsi
@@ -21,7 +21,7 @@
 	qflash0: s25fl128s@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <20000000>;
 		reg = <0>;
 	};
diff --git a/arch/arm/dts/fsl-ls1043a-qds.dtsi b/arch/arm/dts/fsl-ls1043a-qds.dtsi
index 3841aee..70e1a6a 100644
--- a/arch/arm/dts/fsl-ls1043a-qds.dtsi
+++ b/arch/arm/dts/fsl-ls1043a-qds.dtsi
@@ -24,7 +24,7 @@
 	dflash0: n25q128a {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <1000000>; /* input clock */
 		spi-cpol;
 		spi-cpha;
@@ -34,7 +34,7 @@
 	dflash1: sst25wf040b {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <3500000>;
 		spi-cpol;
 		spi-cpha;
@@ -44,7 +44,7 @@
 	dflash2: en25s64 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <3500000>;
 		spi-cpol;
 		spi-cpha;
@@ -59,7 +59,7 @@
 	qflash0: s25fl128s@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <20000000>;
 		reg = <0>;
 	};
diff --git a/arch/arm/dts/fsl-ls1043a-rdb.dts b/arch/arm/dts/fsl-ls1043a-rdb.dts
index c42cad7..721b158 100644
--- a/arch/arm/dts/fsl-ls1043a-rdb.dts
+++ b/arch/arm/dts/fsl-ls1043a-rdb.dts
@@ -26,7 +26,7 @@
 	dspiflash: n25q12a {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		reg = <0>;
 		spi-max-frequency = <1000000>; /* input clock */
 	};
diff --git a/arch/arm/dts/fsl-ls1046a-qds.dtsi b/arch/arm/dts/fsl-ls1046a-qds.dtsi
index ada8a85..c95f44f 100644
--- a/arch/arm/dts/fsl-ls1046a-qds.dtsi
+++ b/arch/arm/dts/fsl-ls1046a-qds.dtsi
@@ -24,7 +24,7 @@
 	dflash0: n25q128a {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <1000000>; /* input clock */
 		spi-cpol;
 		spi-cpha;
@@ -34,7 +34,7 @@
 	dflash1: sst25wf040b {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <3500000>;
 		spi-cpol;
 		spi-cpha;
@@ -44,7 +44,7 @@
 	dflash2: en25s64 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <3500000>;
 		spi-cpol;
 		spi-cpha;
@@ -59,7 +59,7 @@
 	qflash0: s25fl128s@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <20000000>;
 		reg = <0>;
 	};
diff --git a/arch/arm/dts/fsl-ls1046a-rdb.dts b/arch/arm/dts/fsl-ls1046a-rdb.dts
index ba30fd2..a05c9e9 100644
--- a/arch/arm/dts/fsl-ls1046a-rdb.dts
+++ b/arch/arm/dts/fsl-ls1046a-rdb.dts
@@ -26,7 +26,7 @@
 	qflash0: s25fs512s@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <50000000>;
 		reg = <0>;
 	};
@@ -34,7 +34,7 @@
 	qflash1: s25fs512s@1 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <50000000>;
 		reg = <1>;
 	 };
diff --git a/arch/arm/dts/fsl-ls1088a-qds.dts b/arch/arm/dts/fsl-ls1088a-qds.dts
index 4ea451c..8fbb52f 100644
--- a/arch/arm/dts/fsl-ls1088a-qds.dts
+++ b/arch/arm/dts/fsl-ls1088a-qds.dts
@@ -62,7 +62,7 @@
 	dflash0: n25q128a {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		reg = <0>;
 		spi-max-frequency = <1000000>; /* input clock */
 	};
@@ -70,7 +70,7 @@
 	dflash1: sst25wf040b {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <3500000>;
 		reg = <1>;
 	};
@@ -78,7 +78,7 @@
 	dflash2: en25s64 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <3500000>;
 		reg = <2>;
 	};
@@ -91,7 +91,7 @@
 	qflash0: s25fs512s@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <50000000>;
 		reg = <0>;
 	};
@@ -99,7 +99,7 @@
 	qflash1: s25fs512s@1 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <50000000>;
 		reg = <1>;
 	 };
diff --git a/arch/arm/dts/fsl-ls1088a-rdb.dts b/arch/arm/dts/fsl-ls1088a-rdb.dts
index f30bbb7..765d1e3 100644
--- a/arch/arm/dts/fsl-ls1088a-rdb.dts
+++ b/arch/arm/dts/fsl-ls1088a-rdb.dts
@@ -24,7 +24,7 @@
 	qflash0: s25fs512s@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <50000000>;
 		reg = <0>;
 	};
@@ -32,7 +32,7 @@
 	qflash1: s25fs512s@1 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <50000000>;
 		reg = <1>;
 	 };
diff --git a/arch/arm/dts/fsl-ls2080a-qds.dts b/arch/arm/dts/fsl-ls2080a-qds.dts
index 39fbc1b..2a0a528 100644
--- a/arch/arm/dts/fsl-ls2080a-qds.dts
+++ b/arch/arm/dts/fsl-ls2080a-qds.dts
@@ -26,7 +26,7 @@
 	dflash0: n25q128a {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <3000000>;
 		spi-cpol;
 		spi-cpha;
@@ -35,7 +35,7 @@
 	dflash1: sst25wf040b {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <3000000>;
 		spi-cpol;
 		spi-cpha;
@@ -44,7 +44,7 @@
 	dflash2: en25s64 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <3000000>;
 		spi-cpol;
 		spi-cpha;
@@ -59,7 +59,7 @@
 	qflash0: s25fs256s@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <20000000>;
 		reg = <0>;
 	};
diff --git a/arch/arm/dts/fsl-ls2080a-rdb.dts b/arch/arm/dts/fsl-ls2080a-rdb.dts
index e7567cf..0a87cae 100644
--- a/arch/arm/dts/fsl-ls2080a-rdb.dts
+++ b/arch/arm/dts/fsl-ls2080a-rdb.dts
@@ -25,7 +25,7 @@
 	dflash0: n25q512a {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <3000000>;
 		spi-cpol;
 		spi-cpha;
diff --git a/arch/arm/dts/fsl-ls2081a-rdb.dts b/arch/arm/dts/fsl-ls2081a-rdb.dts
index 73e2683..b0b7ef0 100644
--- a/arch/arm/dts/fsl-ls2081a-rdb.dts
+++ b/arch/arm/dts/fsl-ls2081a-rdb.dts
@@ -28,7 +28,7 @@
 	dflash0: n25q512a {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <3000000>;
 		spi-cpol;
 		spi-cpha;
@@ -43,7 +43,7 @@
 	qflash0: s25fs512s@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <50000000>;
 		reg = <0>;
 	};
@@ -51,7 +51,7 @@
 	qflash1: s25fs512s@1 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <50000000>;
 		reg = <1>;
 	};
diff --git a/arch/arm/dts/fsl-ls2088a-rdb-qspi.dts b/arch/arm/dts/fsl-ls2088a-rdb-qspi.dts
index b6d4f0f..bf97d13 100644
--- a/arch/arm/dts/fsl-ls2088a-rdb-qspi.dts
+++ b/arch/arm/dts/fsl-ls2088a-rdb-qspi.dts
@@ -28,7 +28,7 @@
 	dflash0: n25q512a {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <3000000>;
 		spi-cpol;
 		spi-cpha;
@@ -43,7 +43,7 @@
 	qflash0: s25fs512s@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <50000000>;
 		reg = <0>;
 	};
@@ -51,7 +51,7 @@
 	qflash1: s25fs512s@1 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <50000000>;
 		reg = <1>;
 	};
diff --git a/arch/arm/dts/imx53-kp-u-boot.dtsi b/arch/arm/dts/imx53-kp-u-boot.dtsi
new file mode 100644
index 0000000..acab9b3
--- /dev/null
+++ b/arch/arm/dts/imx53-kp-u-boot.dtsi
@@ -0,0 +1,10 @@
+/*
+ * Copyright 2019
+ * Lukasz Majewski, DENX Software Engineering, lukma@denx.de
+ *
+ * SPDX-License-Identifier:     GPL-2.0+ or X11
+ */
+
+&pmic {
+	u-boot,i2c-transaction-bytes = <3>;
+};
diff --git a/arch/arm/dts/imx6sx-sabreauto-u-boot.dtsi b/arch/arm/dts/imx6sx-sabreauto-u-boot.dtsi
index f5c68d7..549461d 100644
--- a/arch/arm/dts/imx6sx-sabreauto-u-boot.dtsi
+++ b/arch/arm/dts/imx6sx-sabreauto-u-boot.dtsi
@@ -7,10 +7,10 @@
 	num-cs = <2>;
 
 	flash0: n25q256a@0 {
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 	};
 
 	flash1: n25q256a@1 {
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 	};
 };
diff --git a/arch/arm/dts/imx6sx-sdb-u-boot.dtsi b/arch/arm/dts/imx6sx-sdb-u-boot.dtsi
index 8e592cd..8f9236d 100644
--- a/arch/arm/dts/imx6sx-sdb-u-boot.dtsi
+++ b/arch/arm/dts/imx6sx-sdb-u-boot.dtsi
@@ -7,10 +7,10 @@
 	num-cs = <2>;
 
 	flash0: n25q256a@0 {
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 	};
 
 	flash1: n25q256a@1 {
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 	};
 };
diff --git a/arch/arm/dts/imx6ul-14x14-evk-u-boot.dtsi b/arch/arm/dts/imx6ul-14x14-evk-u-boot.dtsi
index db640d6..77cb461 100644
--- a/arch/arm/dts/imx6ul-14x14-evk-u-boot.dtsi
+++ b/arch/arm/dts/imx6ul-14x14-evk-u-boot.dtsi
@@ -5,6 +5,6 @@
 
 &qspi {
 	flash0: n25q256a@0 {
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 	};
 };
\ No newline at end of file
diff --git a/arch/arm/dts/imx6ul-9x9-evk-u-boot.dtsi b/arch/arm/dts/imx6ul-9x9-evk-u-boot.dtsi
index db640d6..77cb461 100644
--- a/arch/arm/dts/imx6ul-9x9-evk-u-boot.dtsi
+++ b/arch/arm/dts/imx6ul-9x9-evk-u-boot.dtsi
@@ -5,6 +5,6 @@
 
 &qspi {
 	flash0: n25q256a@0 {
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 	};
 };
\ No newline at end of file
diff --git a/arch/arm/dts/imx6ull-14x14-evk.dts b/arch/arm/dts/imx6ull-14x14-evk.dts
index 8a1b67d..9ebcfe1 100644
--- a/arch/arm/dts/imx6ull-14x14-evk.dts
+++ b/arch/arm/dts/imx6ull-14x14-evk.dts
@@ -455,7 +455,7 @@
 		#address-cells = <1>;
 		#size-cells = <1>;
 		/* compatible = "micron,n25q256a"; */
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <29000000>;
 		spi-nor,ddr-quad-read-dummy = <6>;
 		reg = <0>;
diff --git a/arch/arm/dts/imx7d-sdb-qspi-u-boot.dtsi b/arch/arm/dts/imx7d-sdb-qspi-u-boot.dtsi
index 2ce6961..585af6d 100644
--- a/arch/arm/dts/imx7d-sdb-qspi-u-boot.dtsi
+++ b/arch/arm/dts/imx7d-sdb-qspi-u-boot.dtsi
@@ -5,6 +5,6 @@
 
 &qspi1 {
 	flash0: mx25l51245g@0 {
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 	};
 };
diff --git a/arch/arm/dts/keystone-k2e-evm.dts b/arch/arm/dts/keystone-k2e-evm.dts
index 3be8b53..9288df2 100644
--- a/arch/arm/dts/keystone-k2e-evm.dts
+++ b/arch/arm/dts/keystone-k2e-evm.dts
@@ -123,7 +123,7 @@
 	nor_flash: n25q128a11@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "Micron,n25q128a11", "spi-flash";
+		compatible = "Micron,n25q128a11", "jedec,spi-nor";
 		spi-max-frequency = <54000000>;
 		m25p,fast-read;
 		reg = <0>;
diff --git a/arch/arm/dts/keystone-k2g-evm.dts b/arch/arm/dts/keystone-k2g-evm.dts
index 4820c7e..7c5deef 100644
--- a/arch/arm/dts/keystone-k2g-evm.dts
+++ b/arch/arm/dts/keystone-k2g-evm.dts
@@ -74,7 +74,7 @@
 	spi_nor: flash@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <50000000>;
 		m25p,fast-read;
 		reg = <0>;
@@ -96,7 +96,7 @@
 	status = "okay";
 
 	flash0: m25p80@0 {
-		compatible = "s25fl512s","spi-flash";
+		compatible = "s25fl512s","jedec,spi-nor";
 		reg = <0>;
 		spi-tx-bus-width = <1>;
 		spi-rx-bus-width = <4>;
diff --git a/arch/arm/dts/keystone-k2g-ice.dts b/arch/arm/dts/keystone-k2g-ice.dts
index b67332f..ecca2df 100644
--- a/arch/arm/dts/keystone-k2g-ice.dts
+++ b/arch/arm/dts/keystone-k2g-ice.dts
@@ -39,7 +39,7 @@
 	status = "okay";
 
 	flash0: m25p80@0 {
-		compatible = "s25fl256s1", "spi-flash";
+		compatible = "s25fl256s1", "jedec,spi-nor";
 		reg = <0>;
 		spi-tx-bus-width = <1>;
 		spi-rx-bus-width = <4>;
diff --git a/arch/arm/dts/keystone-k2hk-evm.dts b/arch/arm/dts/keystone-k2hk-evm.dts
index 76a675f..84c58d7 100644
--- a/arch/arm/dts/keystone-k2hk-evm.dts
+++ b/arch/arm/dts/keystone-k2hk-evm.dts
@@ -151,7 +151,7 @@
 	nor_flash: n25q128a11@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "Micron,n25q128a11", "spi-flash";
+		compatible = "Micron,n25q128a11", "jedec,spi-nor";
 		spi-max-frequency = <54000000>;
 		m25p,fast-read;
 		reg = <0>;
diff --git a/arch/arm/dts/keystone-k2l-evm.dts b/arch/arm/dts/keystone-k2l-evm.dts
index b5c5617..91cefdf 100644
--- a/arch/arm/dts/keystone-k2l-evm.dts
+++ b/arch/arm/dts/keystone-k2l-evm.dts
@@ -100,7 +100,7 @@
 	nor_flash: n25q128a11@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "Micron,n25q128a11", "spi-flash";
+		compatible = "Micron,n25q128a11", "jedec,spi-nor";
 		spi-max-frequency = <54000000>;
 		m25p,fast-read;
 		reg = <0>;
diff --git a/arch/arm/dts/kirkwood-atl-sbx81lifkw.dts b/arch/arm/dts/kirkwood-atl-sbx81lifkw.dts
index e5b1efa..4ae74f4 100644
--- a/arch/arm/dts/kirkwood-atl-sbx81lifkw.dts
+++ b/arch/arm/dts/kirkwood-atl-sbx81lifkw.dts
@@ -78,7 +78,7 @@
 	flash@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "st,m25p128", "jedec,spi-nor", "spi-flash";
+		compatible = "st,m25p128", "jedec,spi-nor";
 		reg = <0>;
 		spi-max-frequency = <50000000>;
 		mode = <0>;
diff --git a/arch/arm/dts/kirkwood-atl-sbx81lifxcat.dts b/arch/arm/dts/kirkwood-atl-sbx81lifxcat.dts
index c234449..6e3418f 100644
--- a/arch/arm/dts/kirkwood-atl-sbx81lifxcat.dts
+++ b/arch/arm/dts/kirkwood-atl-sbx81lifxcat.dts
@@ -92,7 +92,7 @@
 	flash@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "st,m25p128", "jedec,spi-nor", "spi-flash";
+		compatible = "st,m25p128", "jedec,spi-nor";
 		reg = <0>;
 		spi-max-frequency = <50000000>;
 		mode = <0>;
diff --git a/arch/arm/dts/kirkwood-dreamplug.dts b/arch/arm/dts/kirkwood-dreamplug.dts
index ccd74dd..e9eea22 100644
--- a/arch/arm/dts/kirkwood-dreamplug.dts
+++ b/arch/arm/dts/kirkwood-dreamplug.dts
@@ -47,7 +47,7 @@
 			m25p40@0 {
 				#address-cells = <1>;
 				#size-cells = <1>;
-				compatible = "mxicy,mx25l1606e", "jedec,spi-nor", "spi-flash";
+				compatible = "mxicy,mx25l1606e", "jedec,spi-nor";
 				reg = <0>;
 				spi-max-frequency = <50000000>;
 				mode = <0>;
diff --git a/arch/arm/dts/kirkwood-lsxl.dtsi b/arch/arm/dts/kirkwood-lsxl.dtsi
index 479a750..c99c0da 100644
--- a/arch/arm/dts/kirkwood-lsxl.dtsi
+++ b/arch/arm/dts/kirkwood-lsxl.dtsi
@@ -79,7 +79,7 @@
 			m25p40@0 {
 				#address-cells = <1>;
 				#size-cells = <1>;
-				compatible = "m25p40", "jedec,spi-nor", "spi-flash";
+				compatible = "m25p40", "jedec,spi-nor";
 				reg = <0>;
 				spi-max-frequency = <25000000>;
 				mode = <0>;
diff --git a/arch/arm/dts/kirkwood-netxbig.dtsi b/arch/arm/dts/kirkwood-netxbig.dtsi
index 135ac80..b573702 100644
--- a/arch/arm/dts/kirkwood-netxbig.dtsi
+++ b/arch/arm/dts/kirkwood-netxbig.dtsi
@@ -32,7 +32,7 @@
 			flash@0 {
 				#address-cells = <1>;
 				#size-cells = <1>;
-				compatible = "mxicy,mx25l4005a", "jedec,spi-nor", "spi-flash";
+				compatible = "mxicy,mx25l4005a", "jedec,spi-nor";
 				reg = <0>;
 				spi-max-frequency = <20000000>;
 				mode = <0>;
diff --git a/arch/arm/dts/kirkwood-ns2-common.dtsi b/arch/arm/dts/kirkwood-ns2-common.dtsi
index f997bb4..51530ea 100644
--- a/arch/arm/dts/kirkwood-ns2-common.dtsi
+++ b/arch/arm/dts/kirkwood-ns2-common.dtsi
@@ -30,7 +30,7 @@
 			flash@0 {
 				#address-cells = <1>;
 				#size-cells = <1>;
-				compatible = "mxicy,mx25l4005a", "jedec,spi-nor", "spi-flash";
+				compatible = "mxicy,mx25l4005a", "jedec,spi-nor";
 				reg = <0>;
 				spi-max-frequency = <20000000>;
 				mode = <0>;
diff --git a/arch/arm/dts/kirkwood-synology.dtsi b/arch/arm/dts/kirkwood-synology.dtsi
index b80d8ee..c97ed29 100644
--- a/arch/arm/dts/kirkwood-synology.dtsi
+++ b/arch/arm/dts/kirkwood-synology.dtsi
@@ -201,7 +201,7 @@
 			m25p80@0 {
 				#address-cells = <1>;
 				#size-cells = <1>;
-				compatible = "st,m25p80", "jedec,spi-nor", "spi-flash";
+				compatible = "st,m25p80", "jedec,spi-nor";
 				reg = <0>;
 				spi-max-frequency = <20000000>;
 				mode = <0>;
diff --git a/arch/arm/dts/ls1021a-iot.dtsi b/arch/arm/dts/ls1021a-iot.dtsi
index d27b601..44dd9b6 100644
--- a/arch/arm/dts/ls1021a-iot.dtsi
+++ b/arch/arm/dts/ls1021a-iot.dtsi
@@ -27,7 +27,7 @@
 	qflash0: n25q128a13@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <20000000>;
 		reg = <0>;
 	};
@@ -40,7 +40,7 @@
 	dspiflash: at26df081a@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <16000000>;
 		spi-cpol;
 		spi-cpha;
diff --git a/arch/arm/dts/ls1021a-qds.dtsi b/arch/arm/dts/ls1021a-qds.dtsi
index f7783e5..b12102a 100644
--- a/arch/arm/dts/ls1021a-qds.dtsi
+++ b/arch/arm/dts/ls1021a-qds.dtsi
@@ -43,7 +43,7 @@
 	qflash0: s25fl128s@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <20000000>;
 		reg = <0>;
 	};
diff --git a/arch/arm/dts/ls1021a-twr.dtsi b/arch/arm/dts/ls1021a-twr.dtsi
index 928e100..5d3275c 100644
--- a/arch/arm/dts/ls1021a-twr.dtsi
+++ b/arch/arm/dts/ls1021a-twr.dtsi
@@ -30,7 +30,7 @@
 	qflash0: n25q128a13@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <20000000>;
 		reg = <0>;
 	};
@@ -43,7 +43,7 @@
 	dspiflash: at26df081a@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <16000000>;
 		spi-cpol;
 		spi-cpha;
diff --git a/arch/arm/dts/mt7629-rfb.dts b/arch/arm/dts/mt7629-rfb.dts
index 95d10aa..4612218 100644
--- a/arch/arm/dts/mt7629-rfb.dts
+++ b/arch/arm/dts/mt7629-rfb.dts
@@ -62,7 +62,7 @@
 	status = "okay";
 
 	spi-flash@0{
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		reg = <0>;
 		u-boot,dm-pre-reloc;
 	};
diff --git a/arch/arm/dts/omap5-u-boot.dtsi b/arch/arm/dts/omap5-u-boot.dtsi
index 54a7285..1b1d765 100644
--- a/arch/arm/dts/omap5-u-boot.dtsi
+++ b/arch/arm/dts/omap5-u-boot.dtsi
@@ -68,7 +68,7 @@
 	u-boot,dm-spl;
 
 	m25p80@0 {
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		u-boot,dm-spl;
 	};
 };
diff --git a/arch/arm/dts/r8a77970-eagle-u-boot.dts b/arch/arm/dts/r8a77970-eagle-u-boot.dts
index 5b17f1d..eb868ed 100644
--- a/arch/arm/dts/r8a77970-eagle-u-boot.dts
+++ b/arch/arm/dts/r8a77970-eagle-u-boot.dts
@@ -44,7 +44,7 @@
 	flash0: spi-flash@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "s25fs512s", "spi-flash", "jedec,spi-nor";
+		compatible = "s25fs512s", "jedec,spi-nor";
 		spi-max-frequency = <50000000>;
 		spi-tx-bus-width = <1>;
 		spi-rx-bus-width = <1>;
diff --git a/arch/arm/dts/rk3288-veyron.dtsi b/arch/arm/dts/rk3288-veyron.dtsi
index 49ba3f3..916dd48 100644
--- a/arch/arm/dts/rk3288-veyron.dtsi
+++ b/arch/arm/dts/rk3288-veyron.dtsi
@@ -307,7 +307,7 @@
 
 	spi_flash: spiflash@0 {
 		u-boot,dm-pre-reloc;
-		compatible = "spidev", "spi-flash";
+		compatible = "spidev", "jedec,spi-nor";
 		spi-max-frequency = <20000000>; /* Reduce for Dediprog em100 pro */
 		reg = <0>;
 	};
diff --git a/arch/arm/dts/rk3368-lion.dts b/arch/arm/dts/rk3368-lion.dts
index 5e578b1..2814542 100644
--- a/arch/arm/dts/rk3368-lion.dts
+++ b/arch/arm/dts/rk3368-lion.dts
@@ -185,7 +185,7 @@
 	#size-cells = <0>;
 
 	spiflash: w25q32dw@0 {
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		reg = <0>;
 		spi-max-frequency = <49500000>;
 		spi-cpol;
diff --git a/arch/arm/dts/rk3399-gru.dtsi b/arch/arm/dts/rk3399-gru.dtsi
index df19263..4cdb432 100644
--- a/arch/arm/dts/rk3399-gru.dtsi
+++ b/arch/arm/dts/rk3399-gru.dtsi
@@ -552,7 +552,7 @@
 
 	spi_flash: spiflash@0 {
 		u-boot,dm-pre-reloc;
-		compatible = "jedec,spi-nor", "spi-flash";
+		compatible = "jedec,spi-nor";
 		reg = <0>;
 
 		/* May run faster once verified. */
diff --git a/arch/arm/dts/rk3399-puma.dtsi b/arch/arm/dts/rk3399-puma.dtsi
index 8304f67..aec13a2 100644
--- a/arch/arm/dts/rk3399-puma.dtsi
+++ b/arch/arm/dts/rk3399-puma.dtsi
@@ -658,7 +658,7 @@
 	spiflash: w25q32dw@0 {
 		u-boot,dm-pre-reloc;
 
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		reg = <0>;
 		spi-max-frequency = <49500000>;
 		spi-cpol;
diff --git a/arch/arm/dts/rv1108-evb.dts b/arch/arm/dts/rv1108-evb.dts
index ccb9969..c91776b 100644
--- a/arch/arm/dts/rv1108-evb.dts
+++ b/arch/arm/dts/rv1108-evb.dts
@@ -45,7 +45,7 @@
 &sfc {
 	status = "okay";
 	flash@0 {
-		compatible = "gd25q256","spi-flash";
+		compatible = "gd25q256","jedec,spi-nor";
 		reg = <0>;
 		spi-tx-bus-width = <1>;
 		spi-rx-bus-width = <1>;
diff --git a/arch/arm/dts/sama5d27_som1.dtsi b/arch/arm/dts/sama5d27_som1.dtsi
index 9efcf63..ea7540b 100644
--- a/arch/arm/dts/sama5d27_som1.dtsi
+++ b/arch/arm/dts/sama5d27_som1.dtsi
@@ -66,7 +66,7 @@
 				u-boot,dm-pre-reloc;
 
 				spi_flash@0 {
-					compatible = "spi-flash";
+					compatible = "jedec,spi-nor";
 					reg = <0>;
 					spi-max-frequency = <50000000>;
 					spi-rx-bus-width = <4>;
diff --git a/arch/arm/dts/sama5d3xmb.dtsi b/arch/arm/dts/sama5d3xmb.dtsi
index f9ef905..c75b76a 100644
--- a/arch/arm/dts/sama5d3xmb.dtsi
+++ b/arch/arm/dts/sama5d3xmb.dtsi
@@ -35,7 +35,7 @@
 				u-boot,dm-pre-reloc;
 
 				spi_flash@0 {
-					compatible = "spi-flash";
+					compatible = "jedec,spi-nor";
 					spi-max-frequency = <50000000>;
 					reg = <0>;
 					u-boot,dm-pre-reloc;
diff --git a/arch/arm/dts/sama5d3xmb_cmp.dtsi b/arch/arm/dts/sama5d3xmb_cmp.dtsi
index 9792b2a..5566fde 100644
--- a/arch/arm/dts/sama5d3xmb_cmp.dtsi
+++ b/arch/arm/dts/sama5d3xmb_cmp.dtsi
@@ -32,7 +32,7 @@
 				dmas = <0>, <0>;	/*  Do not use DMA for spi0 */
 
 				spi_flash@0 {
-					compatible = "spi-flash";
+					compatible = "jedec,spi-nor";
 					spi-max-frequency = <50000000>;
 					reg = <0>;
 				};
diff --git a/arch/arm/dts/socfpga_arria5_socdk-u-boot.dtsi b/arch/arm/dts/socfpga_arria5_socdk-u-boot.dtsi
index c44d1ee..e75f290 100644
--- a/arch/arm/dts/socfpga_arria5_socdk-u-boot.dtsi
+++ b/arch/arm/dts/socfpga_arria5_socdk-u-boot.dtsi
@@ -30,7 +30,7 @@
 };
 
 &flash {
-	compatible = "n25q00", "spi-flash";
+	compatible = "n25q00", "jedec,spi-nor";
 	u-boot,dm-pre-reloc;
 };
 
diff --git a/arch/arm/dts/socfpga_cyclone5_is1.dts b/arch/arm/dts/socfpga_cyclone5_is1.dts
index b7054bf..93e4d45 100644
--- a/arch/arm/dts/socfpga_cyclone5_is1.dts
+++ b/arch/arm/dts/socfpga_cyclone5_is1.dts
@@ -91,7 +91,7 @@
 		u-boot,dm-pre-reloc;
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "n25q00", "spi-flash";
+		compatible = "n25q00", "jedec,spi-nor";
 		reg = <0>;      /* chip select */
 		spi-max-frequency = <100000000>;
 		m25p,fast-read;
diff --git a/arch/arm/dts/socfpga_cyclone5_socdk-u-boot.dtsi b/arch/arm/dts/socfpga_cyclone5_socdk-u-boot.dtsi
index 9436e0f..2fafd7e 100644
--- a/arch/arm/dts/socfpga_cyclone5_socdk-u-boot.dtsi
+++ b/arch/arm/dts/socfpga_cyclone5_socdk-u-boot.dtsi
@@ -34,7 +34,7 @@
 };
 
 &flash0 {
-	compatible = "n25q00", "spi-flash";
+	compatible = "n25q00", "jedec,spi-nor";
 	u-boot,dm-pre-reloc;
 
 	partition@qspi-boot {
diff --git a/arch/arm/dts/socfpga_cyclone5_sockit-u-boot.dtsi b/arch/arm/dts/socfpga_cyclone5_sockit-u-boot.dtsi
index 648f1bd..7ef3053 100644
--- a/arch/arm/dts/socfpga_cyclone5_sockit-u-boot.dtsi
+++ b/arch/arm/dts/socfpga_cyclone5_sockit-u-boot.dtsi
@@ -30,7 +30,7 @@
 };
 
 &flash {
-	compatible = "n25q00", "spi-flash";
+	compatible = "n25q00", "jedec,spi-nor";
 	u-boot,dm-pre-reloc;
 };
 
diff --git a/arch/arm/dts/socfpga_cyclone5_socrates-u-boot.dtsi b/arch/arm/dts/socfpga_cyclone5_socrates-u-boot.dtsi
index 31bd1db..1003115 100644
--- a/arch/arm/dts/socfpga_cyclone5_socrates-u-boot.dtsi
+++ b/arch/arm/dts/socfpga_cyclone5_socrates-u-boot.dtsi
@@ -30,7 +30,7 @@
 };
 
 &flash {
-	compatible = "n25q256a", "spi-flash";
+	compatible = "n25q256a", "jedec,spi-nor";
 	u-boot,dm-pre-reloc;
 };
 
diff --git a/arch/arm/dts/socfpga_cyclone5_sr1500.dts b/arch/arm/dts/socfpga_cyclone5_sr1500.dts
index 6a6c29b..1a18c4f 100644
--- a/arch/arm/dts/socfpga_cyclone5_sr1500.dts
+++ b/arch/arm/dts/socfpga_cyclone5_sr1500.dts
@@ -99,7 +99,7 @@
 		u-boot,dm-pre-reloc;
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "n25q00", "spi-flash";
+		compatible = "n25q00", "jedec,spi-nor";
 		reg = <0>;      /* chip select */
 		spi-max-frequency = <100000000>;
 		m25p,fast-read;
diff --git a/arch/arm/dts/socfpga_cyclone5_vining_fpga-u-boot.dtsi b/arch/arm/dts/socfpga_cyclone5_vining_fpga-u-boot.dtsi
index 360b946..e05ca82 100644
--- a/arch/arm/dts/socfpga_cyclone5_vining_fpga-u-boot.dtsi
+++ b/arch/arm/dts/socfpga_cyclone5_vining_fpga-u-boot.dtsi
@@ -29,11 +29,11 @@
 	u-boot,dm-pre-reloc;
 
 	n25q128@0 {
-		compatible = "n25q128", "spi-flash";
+		compatible = "n25q128", "jedec,spi-nor";
 		u-boot,dm-pre-reloc;
 	};
 	n25q00@1 {
-		compatible = "n25q00", "spi-flash";
+		compatible = "n25q00", "jedec,spi-nor";
 		u-boot,dm-pre-reloc;
 	};
 };
diff --git a/arch/arm/dts/stm32f746-disco.dts b/arch/arm/dts/stm32f746-disco.dts
index 7ef33d6..babd37f 100644
--- a/arch/arm/dts/stm32f746-disco.dts
+++ b/arch/arm/dts/stm32f746-disco.dts
@@ -297,7 +297,7 @@
 	qflash0: n25q128a {
 			#address-cells = <1>;
 			#size-cells = <1>;
-			compatible = "micron,n25q128a13", "spi-flash";
+			compatible = "micron,n25q128a13", "jedec,spi-nor";
 			spi-max-frequency = <108000000>;
 			spi-tx-bus-width = <1>;
 			spi-rx-bus-width = <1>;
diff --git a/arch/arm/dts/stm32f769-disco.dts b/arch/arm/dts/stm32f769-disco.dts
index 1e8ef74..a23d02d 100644
--- a/arch/arm/dts/stm32f769-disco.dts
+++ b/arch/arm/dts/stm32f769-disco.dts
@@ -246,7 +246,7 @@
 	qflash0: n25q128a {
 			#address-cells = <1>;
 			#size-cells = <1>;
-			compatible = "micron,n25q128a13", "spi-flash";
+			compatible = "micron,n25q128a13", "jedec,spi-nor";
 			spi-max-frequency = <108000000>;
 			spi-tx-bus-width = <1>;
 			spi-rx-bus-width = <1>;
diff --git a/arch/arm/dts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi b/arch/arm/dts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi
new file mode 100644
index 0000000..7d9b95c
--- /dev/null
+++ b/arch/arm/dts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi
@@ -0,0 +1,120 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+ *
+ * STM32MP157C DK1/DK2 BOARD configuration
+ * 1x DDR3L 4Gb, 16-bit, 533MHz.
+ * Reference used NT5CC256M16DP-DI from NANYA
+ *
+ * DDR type / Platform	DDR3/3L
+ * freq		533MHz
+ * width	16
+ * datasheet	0  = MT41J256M16-187 / DDR3-1066 bin G
+ * DDR density	4
+ * timing mode	optimized
+ * Scheduling/QoS options : type = 2
+ * address mapping : RBC
+ * Tc > + 85C : N
+ */
+#define DDR_MEM_NAME "DDR3-1066/888 bin G 1x4Gb 533MHz v1.43"
+#define DDR_MEM_SPEED 533
+#define DDR_MEM_SIZE 0x20000000
+
+#define DDR_MSTR 0x00041401
+#define DDR_MRCTRL0 0x00000010
+#define DDR_MRCTRL1 0x00000000
+#define DDR_DERATEEN 0x00000000
+#define DDR_DERATEINT 0x00800000
+#define DDR_PWRCTL 0x00000000
+#define DDR_PWRTMG 0x00400010
+#define DDR_HWLPCTL 0x00000000
+#define DDR_RFSHCTL0 0x00210000
+#define DDR_RFSHCTL3 0x00000000
+#define DDR_RFSHTMG 0x0081008B
+#define DDR_CRCPARCTL0 0x00000000
+#define DDR_DRAMTMG0 0x121B2414
+#define DDR_DRAMTMG1 0x000A041C
+#define DDR_DRAMTMG2 0x0608090F
+#define DDR_DRAMTMG3 0x0050400C
+#define DDR_DRAMTMG4 0x08040608
+#define DDR_DRAMTMG5 0x06060403
+#define DDR_DRAMTMG6 0x02020002
+#define DDR_DRAMTMG7 0x00000202
+#define DDR_DRAMTMG8 0x00001005
+#define DDR_DRAMTMG14 0x000000A0
+#define DDR_ZQCTL0 0xC2000040
+#define DDR_DFITMG0 0x02060105
+#define DDR_DFITMG1 0x00000202
+#define DDR_DFILPCFG0 0x07000000
+#define DDR_DFIUPD0 0xC0400003
+#define DDR_DFIUPD1 0x00000000
+#define DDR_DFIUPD2 0x00000000
+#define DDR_DFIPHYMSTR 0x00000000
+#define DDR_ADDRMAP1 0x00070707
+#define DDR_ADDRMAP2 0x00000000
+#define DDR_ADDRMAP3 0x1F000000
+#define DDR_ADDRMAP4 0x00001F1F
+#define DDR_ADDRMAP5 0x06060606
+#define DDR_ADDRMAP6 0x0F060606
+#define DDR_ADDRMAP9 0x00000000
+#define DDR_ADDRMAP10 0x00000000
+#define DDR_ADDRMAP11 0x00000000
+#define DDR_ODTCFG 0x06000600
+#define DDR_ODTMAP 0x00000001
+#define DDR_SCHED 0x00000C01
+#define DDR_SCHED1 0x00000000
+#define DDR_PERFHPR1 0x01000001
+#define DDR_PERFLPR1 0x08000200
+#define DDR_PERFWR1 0x08000400
+#define DDR_DBG0 0x00000000
+#define DDR_DBG1 0x00000000
+#define DDR_DBGCMD 0x00000000
+#define DDR_POISONCFG 0x00000000
+#define DDR_PCCFG 0x00000010
+#define DDR_PCFGR_0 0x00010000
+#define DDR_PCFGW_0 0x00000000
+#define DDR_PCFGQOS0_0 0x02100C03
+#define DDR_PCFGQOS1_0 0x00800100
+#define DDR_PCFGWQOS0_0 0x01100C03
+#define DDR_PCFGWQOS1_0 0x01000200
+#define DDR_PCFGR_1 0x00010000
+#define DDR_PCFGW_1 0x00000000
+#define DDR_PCFGQOS0_1 0x02100C03
+#define DDR_PCFGQOS1_1 0x00800040
+#define DDR_PCFGWQOS0_1 0x01100C03
+#define DDR_PCFGWQOS1_1 0x01000200
+#define DDR_PGCR 0x01442E02
+#define DDR_PTR0 0x0022AA5B
+#define DDR_PTR1 0x04841104
+#define DDR_PTR2 0x042DA068
+#define DDR_ACIOCR 0x10400812
+#define DDR_DXCCR 0x00000C40
+#define DDR_DSGCR 0xF200001F
+#define DDR_DCR 0x0000000B
+#define DDR_DTPR0 0x38D488D0
+#define DDR_DTPR1 0x098B00D8
+#define DDR_DTPR2 0x10023600
+#define DDR_MR0 0x00000840
+#define DDR_MR1 0x00000000
+#define DDR_MR2 0x00000208
+#define DDR_MR3 0x00000000
+#define DDR_ODTCR 0x00010000
+#define DDR_ZQ0CR1 0x00000038
+#define DDR_DX0GCR 0x0000CE81
+#define DDR_DX0DLLCR 0x40000000
+#define DDR_DX0DQTR 0xFFFFFFFF
+#define DDR_DX0DQSTR 0x3DB02000
+#define DDR_DX1GCR 0x0000CE81
+#define DDR_DX1DLLCR 0x40000000
+#define DDR_DX1DQTR 0xFFFFFFFF
+#define DDR_DX1DQSTR 0x3DB02000
+#define DDR_DX2GCR 0x0000CE81
+#define DDR_DX2DLLCR 0x40000000
+#define DDR_DX2DQTR 0xFFFFFFFF
+#define DDR_DX2DQSTR 0x3DB02000
+#define DDR_DX3GCR 0x0000CE81
+#define DDR_DX3DLLCR 0x40000000
+#define DDR_DX3DQTR 0xFFFFFFFF
+#define DDR_DX3DQSTR 0x3DB02000
+
+#include "stm32mp15-ddr.dtsi"
diff --git a/arch/arm/dts/stm32mp157-pinctrl.dtsi b/arch/arm/dts/stm32mp157-pinctrl.dtsi
index 85da592..c069875 100644
--- a/arch/arm/dts/stm32mp157-pinctrl.dtsi
+++ b/arch/arm/dts/stm32mp157-pinctrl.dtsi
@@ -148,6 +148,13 @@
 				gpio-ranges = <&pinctrl 0 160 8>;
 			};
 
+			adc12_usb_pwr_pins_a: adc12-usb-pwr-pins-0 {
+				pins {
+					pinmux = <STM32_PINMUX('A', 4, ANALOG)>, /* ADC12 in18 */
+						 <STM32_PINMUX('A', 5, ANALOG)>; /* ADC12 in19 */
+				};
+			};
+
 			cec_pins_a: cec-0 {
 				pins {
 					pinmux = <STM32_PINMUX('A', 15, AF4)>;
@@ -157,6 +164,52 @@
 				};
 			};
 
+			ethernet0_rgmii_pins_a: rgmii-0 {
+				pins1 {
+					pinmux = <STM32_PINMUX('G', 5, AF11)>, /* ETH_RGMII_CLK125 */
+						 <STM32_PINMUX('G', 4, AF11)>, /* ETH_RGMII_GTX_CLK */
+						 <STM32_PINMUX('G', 13, AF11)>, /* ETH_RGMII_TXD0 */
+						 <STM32_PINMUX('G', 14, AF11)>, /* ETH_RGMII_TXD1 */
+						 <STM32_PINMUX('C', 2, AF11)>, /* ETH_RGMII_TXD2 */
+						 <STM32_PINMUX('E', 2, AF11)>, /* ETH_RGMII_TXD3 */
+						 <STM32_PINMUX('B', 11, AF11)>, /* ETH_RGMII_TX_CTL */
+						 <STM32_PINMUX('A', 2, AF11)>, /* ETH_MDIO */
+						 <STM32_PINMUX('C', 1, AF11)>; /* ETH_MDC */
+					bias-disable;
+					drive-push-pull;
+					slew-rate = <3>;
+				};
+				pins2 {
+					pinmux = <STM32_PINMUX('C', 4, AF11)>, /* ETH_RGMII_RXD0 */
+						 <STM32_PINMUX('C', 5, AF11)>, /* ETH_RGMII_RXD1 */
+						 <STM32_PINMUX('B', 0, AF11)>, /* ETH_RGMII_RXD2 */
+						 <STM32_PINMUX('B', 1, AF11)>, /* ETH_RGMII_RXD3 */
+						 <STM32_PINMUX('A', 1, AF11)>, /* ETH_RGMII_RX_CLK */
+						 <STM32_PINMUX('A', 7, AF11)>; /* ETH_RGMII_RX_CTL */
+					bias-disable;
+				};
+			};
+
+			ethernet0_rgmii_pins_sleep_a: rgmii-sleep-0 {
+				pins1 {
+					pinmux = <STM32_PINMUX('G', 5, ANALOG)>, /* ETH_RGMII_CLK125 */
+						 <STM32_PINMUX('G', 4, ANALOG)>, /* ETH_RGMII_GTX_CLK */
+						 <STM32_PINMUX('G', 13, ANALOG)>, /* ETH_RGMII_TXD0 */
+						 <STM32_PINMUX('G', 14, ANALOG)>, /* ETH_RGMII_TXD1 */
+						 <STM32_PINMUX('C', 2, ANALOG)>, /* ETH_RGMII_TXD2 */
+						 <STM32_PINMUX('E', 2, ANALOG)>, /* ETH_RGMII_TXD3 */
+						 <STM32_PINMUX('B', 11, ANALOG)>, /* ETH_RGMII_TX_CTL */
+						 <STM32_PINMUX('A', 2, ANALOG)>, /* ETH_MDIO */
+						 <STM32_PINMUX('C', 1, ANALOG)>, /* ETH_MDC */
+						 <STM32_PINMUX('C', 4, ANALOG)>, /* ETH_RGMII_RXD0 */
+						 <STM32_PINMUX('C', 5, ANALOG)>, /* ETH_RGMII_RXD1 */
+						 <STM32_PINMUX('B', 0, ANALOG)>, /* ETH_RGMII_RXD2 */
+						 <STM32_PINMUX('B', 1, ANALOG)>, /* ETH_RGMII_RXD3 */
+						 <STM32_PINMUX('A', 1, ANALOG)>, /* ETH_RGMII_RX_CLK */
+						 <STM32_PINMUX('A', 7, ANALOG)>; /* ETH_RGMII_RX_CTL */
+				};
+			};
+
 			i2c1_pins_a: i2c1-0 {
 				pins {
 					pinmux = <STM32_PINMUX('D', 12, AF5)>, /* I2C1_SCL */
@@ -187,6 +240,19 @@
 				};
 			};
 
+			m_can1_pins_a: m-can1-0 {
+				pins1 {
+					pinmux = <STM32_PINMUX('H', 13, AF9)>; /* CAN1_TX */
+					slew-rate = <1>;
+					drive-push-pull;
+					bias-disable;
+				};
+				pins2 {
+					pinmux = <STM32_PINMUX('I', 9, AF9)>; /* CAN1_RX */
+					bias-disable;
+				};
+			};
+
 			pwm2_pins_a: pwm2-0 {
 				pins {
 					pinmux = <STM32_PINMUX('A', 3, AF1)>; /* TIM2_CH4 */
@@ -360,6 +426,21 @@
 					slew-rate = <0>;
 				};
 			};
+
+			spi1_pins_a: spi1-0 {
+				pins1 {
+					pinmux = <STM32_PINMUX('Z', 0, AF5)>, /* SPI1_SCK */
+						 <STM32_PINMUX('Z', 2, AF5)>; /* SPI1_MOSI */
+					bias-disable;
+					drive-push-pull;
+					slew-rate = <1>;
+				};
+
+				pins2 {
+					pinmux = <STM32_PINMUX('Z', 1, AF5)>; /* SPI1_MISO */
+					bias-disable;
+				};
+			};
 		};
 	};
 };
diff --git a/arch/arm/dts/stm32mp157-u-boot.dtsi b/arch/arm/dts/stm32mp157-u-boot.dtsi
index 90d13f3..ab6f673 100644
--- a/arch/arm/dts/stm32mp157-u-boot.dtsi
+++ b/arch/arm/dts/stm32mp157-u-boot.dtsi
@@ -17,6 +17,8 @@
 		gpio9 = &gpioj;
 		gpio10 = &gpiok;
 		gpio25 = &gpioz;
+		pinctrl0 = &pinctrl;
+		pinctrl1 = &pinctrl_z;
 	};
 
 	config {
@@ -39,6 +41,10 @@
 	};
 };
 
+&bsec {
+	u-boot,dm-pre-reloc;
+};
+
 &clk_hsi {
 	u-boot,dm-pre-reloc;
 };
diff --git a/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi b/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi
new file mode 100644
index 0000000..af7acfa
--- /dev/null
+++ b/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi
@@ -0,0 +1,199 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright : STMicroelectronics 2018
+ */
+
+#include <dt-bindings/clock/stm32mp1-clksrc.h>
+#include "stm32mp157-u-boot.dtsi"
+#include "stm32mp15-ddr3-1x4Gb-1066-binG.dtsi"
+
+/ {
+	aliases {
+		i2c3 = &i2c4;
+		mmc0 = &sdmmc1;
+	};
+	config {
+		u-boot,boot-led = "heartbeat";
+		u-boot,error-led = "error";
+		st,adc_usb_pd = <&adc1 18>, <&adc1 19>;
+	};
+	led {
+		red {
+			label = "error";
+			gpios = <&gpioa 13 GPIO_ACTIVE_LOW>;
+			default-state = "off";
+			status = "okay";
+		};
+
+		blue {
+			default-state = "on";
+		};
+	};
+};
+
+&adc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&adc12_usb_pwr_pins_a>;
+	vdd-supply = <&vdd>;
+	vdda-supply = <&vdd>;
+	vref-supply = <&vrefbuf>;
+	status = "okay";
+	adc1: adc@0 {
+		/*
+		 * Type-C USB_PWR_CC1 & USB_PWR_CC2 on in18 & in19.
+		 * Use at least 5 * RC time, e.g. 5 * (Rp + Rd) * C:
+		 * 5 * (56 + 47kOhms) * 5pF => 2.5us.
+		 * Use arbitrary margin here (e.g. 5µs).
+		 */
+		st,min-sample-time-nsecs = <5000>;
+		/* ANA0, ANA1, USB Type-C CC1 & CC2 */
+		st,adc-channels = <0 1 18 19>;
+		status = "okay";
+	};
+};
+
+&clk_hse {
+	st,digbypass;
+};
+
+&i2c4 {
+	u-boot,dm-pre-reloc;
+};
+
+&i2c4_pins_a {
+	u-boot,dm-pre-reloc;
+	pins {
+		u-boot,dm-pre-reloc;
+	};
+};
+
+&pmic {
+	u-boot,dm-pre-reloc;
+};
+
+&rcc {
+	st,clksrc = <
+		CLK_MPU_PLL1P
+		CLK_AXI_PLL2P
+		CLK_MCU_PLL3P
+		CLK_PLL12_HSE
+		CLK_PLL3_HSE
+		CLK_PLL4_HSE
+		CLK_RTC_LSE
+		CLK_MCO1_DISABLED
+		CLK_MCO2_DISABLED
+	>;
+
+	st,clkdiv = <
+		1 /*MPU*/
+		0 /*AXI*/
+		0 /*MCU*/
+		1 /*APB1*/
+		1 /*APB2*/
+		1 /*APB3*/
+		1 /*APB4*/
+		2 /*APB5*/
+		23 /*RTC*/
+		0 /*MCO1*/
+		0 /*MCO2*/
+	>;
+
+	st,pkcs = <
+		CLK_CKPER_HSE
+		CLK_FMC_ACLK
+		CLK_QSPI_ACLK
+		CLK_ETH_DISABLED
+		CLK_SDMMC12_PLL4P
+		CLK_DSI_DSIPLL
+		CLK_STGEN_HSE
+		CLK_USBPHY_HSE
+		CLK_SPI2S1_PLL3Q
+		CLK_SPI2S23_PLL3Q
+		CLK_SPI45_HSI
+		CLK_SPI6_HSI
+		CLK_I2C46_HSI
+		CLK_SDMMC3_PLL4P
+		CLK_USBO_USBPHY
+		CLK_ADC_CKPER
+		CLK_CEC_LSE
+		CLK_I2C12_HSI
+		CLK_I2C35_HSI
+		CLK_UART1_HSI
+		CLK_UART24_HSI
+		CLK_UART35_HSI
+		CLK_UART6_HSI
+		CLK_UART78_HSI
+		CLK_SPDIF_PLL4P
+		CLK_FDCAN_PLL4Q
+		CLK_SAI1_PLL3Q
+		CLK_SAI2_PLL3Q
+		CLK_SAI3_PLL3Q
+		CLK_SAI4_PLL3Q
+		CLK_RNG1_LSI
+		CLK_RNG2_LSI
+		CLK_LPTIM1_PCLK1
+		CLK_LPTIM23_PCLK3
+		CLK_LPTIM45_LSE
+	>;
+
+	/* VCO = 1300.0 MHz => P = 650 (CPU) */
+	pll1: st,pll@0 {
+		cfg = < 2 80 0 0 0 PQR(1,0,0) >;
+		frac = < 0x800 >;
+		u-boot,dm-pre-reloc;
+	};
+
+	/* VCO = 1066.0 MHz => P = 266 (AXI), Q = 533 (GPU), R = 533 (DDR) */
+	pll2: st,pll@1 {
+		cfg = < 2 65 1 0 0 PQR(1,1,1) >;
+		frac = < 0x1400 >;
+		u-boot,dm-pre-reloc;
+	};
+
+	/* VCO = 417.8 MHz => P = 209, Q = 24, R = 11 */
+	pll3: st,pll@2 {
+		cfg = < 1 33 1 16 36 PQR(1,1,1) >;
+		frac = < 0x1a04 >;
+		u-boot,dm-pre-reloc;
+	};
+
+	/* VCO = 594.0 MHz => P = 99, Q = 74, R = 74 */
+	pll4: st,pll@3 {
+		cfg = < 3 98 5 7 7 PQR(1,1,1) >;
+		u-boot,dm-pre-reloc;
+	};
+};
+
+&sdmmc1 {
+	u-boot,dm-spl;
+};
+
+&sdmmc1_b4_pins_a {
+	u-boot,dm-spl;
+	pins {
+		u-boot,dm-spl;
+	};
+};
+
+&uart4 {
+	u-boot,dm-pre-reloc;
+};
+
+&uart4_pins_a {
+	u-boot,dm-pre-reloc;
+	pins1 {
+		u-boot,dm-pre-reloc;
+	};
+	pins2 {
+		u-boot,dm-pre-reloc;
+	};
+};
+
+&usbotg_hs {
+	usb1600;
+	hnp-srp-disable;
+};
+
+&v3v3 {
+	regulator-always-on;
+};
diff --git a/arch/arm/dts/stm32mp157a-dk1.dts b/arch/arm/dts/stm32mp157a-dk1.dts
new file mode 100644
index 0000000..0882765
--- /dev/null
+++ b/arch/arm/dts/stm32mp157a-dk1.dts
@@ -0,0 +1,262 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved
+ * Author: Alexandre Torgue <alexandre.torgue@st.com> for STMicroelectronics.
+ */
+
+/dts-v1/;
+
+#include "stm32mp157c.dtsi"
+#include "stm32mp157-pinctrl.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/mfd/st,stpmic1.h>
+
+/ {
+	model = "STMicroelectronics STM32MP157A-DK1 Discovery Board";
+	compatible = "st,stm32mp157a-dk1", "st,stm32mp157";
+
+	aliases {
+		ethernet0 = &ethernet0;
+		serial0 = &uart4;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	memory@c0000000 {
+		reg = <0xc0000000 0x20000000>;
+	};
+
+	led {
+		compatible = "gpio-leds";
+		blue {
+			label = "heartbeat";
+			gpios = <&gpiod 11 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "heartbeat";
+			default-state = "off";
+		};
+	};
+};
+
+&ethernet0 {
+	status = "okay";
+	pinctrl-0 = <&ethernet0_rgmii_pins_a>;
+	pinctrl-1 = <&ethernet0_rgmii_pins_sleep_a>;
+	pinctrl-names = "default", "sleep";
+	phy-mode = "rgmii";
+	max-speed = <1000>;
+	phy-handle = <&phy0>;
+
+	mdio0 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "snps,dwmac-mdio";
+		phy0: ethernet-phy@0 {
+			reg = <0>;
+		};
+	};
+};
+
+&i2c4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c4_pins_a>;
+	i2c-scl-rising-time-ns = <185>;
+	i2c-scl-falling-time-ns = <20>;
+	status = "okay";
+	/delete-property/dmas;
+	/delete-property/dma-names;
+
+	pmic: stpmic@33 {
+		compatible = "st,stpmic1";
+		reg = <0x33>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		status = "okay";
+
+		st,main-control-register = <0x04>;
+		st,vin-control-register = <0xc0>;
+		st,usb-control-register = <0x20>;
+
+		regulators {
+			compatible = "st,stpmic1-regulators";
+
+			ldo1-supply = <&v3v3>;
+			ldo3-supply = <&vdd_ddr>;
+			ldo6-supply = <&v3v3>;
+			pwr_sw1-supply = <&bst_out>;
+			pwr_sw2-supply = <&bst_out>;
+
+			vddcore: buck1 {
+				regulator-name = "vddcore";
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-always-on;
+				regulator-initial-mode = <0>;
+				regulator-over-current-protection;
+			};
+
+			vdd_ddr: buck2 {
+				regulator-name = "vdd_ddr";
+				regulator-min-microvolt = <1350000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-always-on;
+				regulator-initial-mode = <0>;
+				regulator-over-current-protection;
+			};
+
+			vdd: buck3 {
+				regulator-name = "vdd";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+				st,mask-reset;
+				regulator-initial-mode = <0>;
+				regulator-over-current-protection;
+			};
+
+			v3v3: buck4 {
+				regulator-name = "v3v3";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+				regulator-over-current-protection;
+				regulator-initial-mode = <0>;
+			};
+
+			v1v8_audio: ldo1 {
+				regulator-name = "v1v8_audio";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+				interrupts = <IT_CURLIM_LDO1 0>;
+			};
+
+			v3v3_hdmi: ldo2 {
+				regulator-name = "v3v3_hdmi";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+				interrupts = <IT_CURLIM_LDO2 0>;
+			};
+
+			vtt_ddr: ldo3 {
+				regulator-name = "vtt_ddr";
+				regulator-min-microvolt = <500000>;
+				regulator-max-microvolt = <750000>;
+				regulator-always-on;
+				regulator-over-current-protection;
+			};
+
+			vdd_usb: ldo4 {
+				regulator-name = "vdd_usb";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				interrupts = <IT_CURLIM_LDO4 0>;
+			};
+
+			vdda: ldo5 {
+				regulator-name = "vdda";
+				regulator-min-microvolt = <2900000>;
+				regulator-max-microvolt = <2900000>;
+				interrupts = <IT_CURLIM_LDO5 0>;
+				regulator-boot-on;
+			};
+
+			v1v2_hdmi: ldo6 {
+				regulator-name = "v1v2_hdmi";
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <1200000>;
+				regulator-always-on;
+				interrupts = <IT_CURLIM_LDO6 0>;
+
+			};
+
+			vref_ddr: vref_ddr {
+				regulator-name = "vref_ddr";
+				regulator-always-on;
+				regulator-over-current-protection;
+			};
+
+			 bst_out: boost {
+				regulator-name = "bst_out";
+				interrupts = <IT_OCP_BOOST 0>;
+			 };
+
+			vbus_otg: pwr_sw1 {
+				regulator-name = "vbus_otg";
+				interrupts = <IT_OCP_OTG 0>;
+				regulator-active-discharge;
+			 };
+
+			 vbus_sw: pwr_sw2 {
+				regulator-name = "vbus_sw";
+				interrupts = <IT_OCP_SWOUT 0>;
+				regulator-active-discharge;
+			 };
+		};
+
+		onkey {
+			compatible = "st,stpmic1-onkey";
+			interrupts = <IT_PONKEY_F 0>, <IT_PONKEY_R 1>;
+			interrupt-names = "onkey-falling", "onkey-rising";
+			status = "okay";
+		};
+
+		watchdog {
+			compatible = "st,stpmic1-wdt";
+			status = "disabled";
+		};
+	};
+};
+
+&iwdg2 {
+	timeout-sec = <32>;
+	status = "okay";
+};
+
+&pwr {
+	pwr-supply = <&vdd>;
+};
+
+&rng1 {
+	status = "okay";
+};
+
+&rtc {
+	status = "okay";
+};
+
+&sdmmc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&sdmmc1_b4_pins_a>;
+	broken-cd;
+	st,neg-edge;
+	bus-width = <4>;
+	vmmc-supply = <&v3v3>;
+	status = "okay";
+};
+
+&uart4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart4_pins_a>;
+	status = "okay";
+};
+
+&usbh_ehci {
+	phys = <&usbphyc_port0>;
+	phy-names = "usb";
+	status = "okay";
+};
+
+&usbphyc {
+	vdd3v3-supply = <&vdd_usb>;
+	status = "okay";
+};
+
+&vrefbuf {
+	regulator-min-microvolt = <2500000>;
+	regulator-max-microvolt = <2500000>;
+	vdda-supply = <&vdd>;
+	status = "okay";
+};
diff --git a/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi b/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi
new file mode 100644
index 0000000..06ef3a4
--- /dev/null
+++ b/arch/arm/dts/stm32mp157c-dk2-u-boot.dtsi
@@ -0,0 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright : STMicroelectronics 2018
+ */
+
+#include "stm32mp157a-dk1-u-boot.dtsi"
diff --git a/arch/arm/dts/stm32mp157c-dk2.dts b/arch/arm/dts/stm32mp157c-dk2.dts
new file mode 100644
index 0000000..9a81d2d
--- /dev/null
+++ b/arch/arm/dts/stm32mp157c-dk2.dts
@@ -0,0 +1,67 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (C) STMicroelectronics 2019 - All Rights Reserved
+ * Author: Alexandre Torgue <alexandre.torgue@st.com> for STMicroelectronics.
+ */
+
+/dts-v1/;
+
+#include "stm32mp157a-dk1.dts"
+
+/ {
+	model = "STMicroelectronics STM32MP157C-DK2 Discovery Board";
+	compatible = "st,stm32mp157c-dk2", "st,stm32mp157";
+};
+
+&dsi {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	status = "okay";
+	phy-dsi-supply = <&reg18>;
+
+	ports {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		port@0 {
+			reg = <0>;
+			dsi_in: endpoint {
+				remote-endpoint = <&ltdc_ep1_out>;
+			};
+		};
+
+		port@1 {
+			reg = <1>;
+			dsi_out: endpoint {
+				remote-endpoint = <&panel_in>;
+			};
+		};
+	};
+
+	panel@0 {
+		compatible = "orisetech,otm8009a";
+		reg = <0>;
+		reset-gpios = <&gpioe 4 GPIO_ACTIVE_LOW>;
+		status = "okay";
+
+		port {
+			panel_in: endpoint {
+				remote-endpoint = <&dsi_out>;
+			};
+		};
+	};
+};
+
+&ltdc {
+	status = "okay";
+
+	port {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		ltdc_ep1_out: endpoint@1 {
+			reg = <1>;
+			remote-endpoint = <&dsi_in>;
+		};
+	};
+};
diff --git a/arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi b/arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi
index 70bbf66..55f9903 100644
--- a/arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi
+++ b/arch/arm/dts/stm32mp157c-ed1-u-boot.dtsi
@@ -9,11 +9,16 @@
 
 / {
 	aliases {
+		i2c3 = &i2c4;
 		mmc0 = &sdmmc1;
 		mmc1 = &sdmmc2;
-		i2c3 = &i2c4;
 	};
 
+	config {
+		st,fastboot-gpios = <&gpioa 13 GPIO_ACTIVE_LOW>;
+		st,stm32prog-gpios = <&gpioa 14 GPIO_ACTIVE_LOW>;
+	};
+
 	led {
 		compatible = "gpio-leds";
 
@@ -43,14 +48,8 @@
 	st,digbypass;
 };
 
-&uart4_pins_a {
+&i2c4 {
 	u-boot,dm-pre-reloc;
-	pins1 {
-		u-boot,dm-pre-reloc;
-	};
-	pins2 {
-		u-boot,dm-pre-reloc;
-	};
 };
 
 &i2c4_pins_a {
@@ -60,14 +59,6 @@
 	};
 };
 
-&uart4 {
-	u-boot,dm-pre-reloc;
-};
-
-&i2c4 {
-	u-boot,dm-pre-reloc;
-};
-
 &pmic {
 	u-boot,dm-pre-reloc;
 };
@@ -165,8 +156,6 @@
 	};
 };
 
-/* SPL part **************************************/
-/* MMC1 boot */
 &sdmmc1_b4_pins_a {
 	u-boot,dm-spl;
 	pins {
@@ -185,7 +174,6 @@
 	u-boot,dm-spl;
 };
 
-/* MMC2 boot */
 &sdmmc2_b4_pins_a {
 	u-boot,dm-spl;
 	pins {
@@ -203,3 +191,17 @@
 &sdmmc2 {
 	u-boot,dm-spl;
 };
+
+&uart4 {
+	u-boot,dm-pre-reloc;
+};
+
+&uart4_pins_a {
+	u-boot,dm-pre-reloc;
+	pins1 {
+		u-boot,dm-pre-reloc;
+	};
+	pins2 {
+		u-boot,dm-pre-reloc;
+	};
+};
diff --git a/arch/arm/dts/stm32mp157c-ed1.dts b/arch/arm/dts/stm32mp157c-ed1.dts
index 7a9b742..2664c9c 100644
--- a/arch/arm/dts/stm32mp157c-ed1.dts
+++ b/arch/arm/dts/stm32mp157c-ed1.dts
@@ -8,20 +8,24 @@
 #include "stm32mp157c.dtsi"
 #include "stm32mp157-pinctrl.dtsi"
 #include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/mfd/st,stpmu1.h>
+#include <dt-bindings/mfd/st,stpmic1.h>
 
 / {
 	model = "STMicroelectronics STM32MP157C eval daughter";
 	compatible = "st,stm32mp157c-ed1", "st,stm32mp157";
 
 	chosen {
-		stdout-path = "serial3:115200n8";
+		stdout-path = "serial0:115200n8";
 	};
 
 	memory@c0000000 {
 		reg = <0xC0000000 0x40000000>;
 	};
 
+	aliases {
+		serial0 = &uart4;
+	};
+
 	sd_switch: regulator-sd_switch {
 		compatible = "regulator-gpio";
 		regulator-name = "sd_switch";
@@ -36,15 +40,8 @@
 	};
 };
 
-&rng1 {
-	status = "okay";
-};
-
-&timers6 {
+&hwspinlock {
 	status = "okay";
-	timer@5 {
-		status = "okay";
-	};
 };
 
 &i2c4 {
@@ -54,8 +51,8 @@
 	i2c-scl-falling-time-ns = <20>;
 	status = "okay";
 
-	pmic: stpmu1@33 {
-		compatible = "st,stpmu1";
+	pmic: stpmic1@33 {
+		compatible = "st,stpmic1";
 		reg = <0x33>;
 		interrupts = <0 2>;
 		interrupt-parent = <&gpioa>;
@@ -68,7 +65,7 @@
 		st,usb_control_register = <0x30>;
 
 		regulators {
-			compatible = "st,stpmu1-regulators";
+			compatible = "st,stpmic1-regulators";
 
 			ldo1-supply = <&v3v3>;
 			ldo2-supply = <&v3v3>;
@@ -321,10 +318,27 @@
 	};
 };
 
+&iwdg2 {
+	timeout-sec = <32>;
+	status = "okay";
+};
+
+&pinctrl {
+	hwlocks = <&hwspinlock 0>;
+};
+
 &pwr {
 	pwr-supply = <&vdd>;
 };
 
+&rng1 {
+	status = "okay";
+};
+
+&rtc {
+	status = "okay";
+};
+
 &sdmmc1 {
 	pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_dir_pins_a>;
 	broken-cd;
@@ -355,6 +369,13 @@
 	status = "okay";
 };
 
+&timers6 {
+	status = "okay";
+	timer@5 {
+		status = "okay";
+	};
+};
+
 &uart4 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart4_pins_a>;
@@ -365,14 +386,6 @@
 	usb33d-supply = <&usb33>;
 };
 
-&hwspinlock {
-	status = "okay";
-};
-
-&pinctrl {
-	hwlocks = <&hwspinlock 0>;
-};
-
 &usbphyc_port0 {
 	phy-supply = <&vdd_usb>;
 	vdda1v1-supply = <&reg11>;
diff --git a/arch/arm/dts/stm32mp157c-ev1-u-boot.dtsi b/arch/arm/dts/stm32mp157c-ev1-u-boot.dtsi
index 30b1734..8b92b1f 100644
--- a/arch/arm/dts/stm32mp157c-ev1-u-boot.dtsi
+++ b/arch/arm/dts/stm32mp157c-ev1-u-boot.dtsi
@@ -7,29 +7,23 @@
 
 / {
 	aliases {
-		spi0 = &qspi;
+		gpio26 = &stmfx_pinctrl;
 		i2c1 = &i2c2;
 		i2c4 = &i2c5;
+		pinctrl2 = &stmfx_pinctrl;
+		spi0 = &qspi;
 	};
 };
 
 &flash0 {
-	compatible = "spi-flash";
+	compatible = "jedec,spi-nor";
+	u-boot,dm-spl;
 };
 
 &flash1 {
-	compatible = "spi-flash";
-};
-
-&v3v3 {
-	regulator-always-on;
-};
-
-&usbotg_hs {
-	g-tx-fifo-size = <576>;
+	compatible = "jedec,spi-nor";
 };
 
-/* SPL part **************************************/
 &qspi {
 	u-boot,dm-spl;
 };
@@ -61,7 +55,10 @@
 	};
 };
 
-&flash0 {
-	u-boot,dm-spl;
+&usbotg_hs {
+	g-tx-fifo-size = <576>;
 };
 
+&v3v3 {
+	regulator-always-on;
+};
diff --git a/arch/arm/dts/stm32mp157c-ev1.dts b/arch/arm/dts/stm32mp157c-ev1.dts
index 902a42b..a6ee379 100644
--- a/arch/arm/dts/stm32mp157c-ev1.dts
+++ b/arch/arm/dts/stm32mp157c-ev1.dts
@@ -11,6 +11,21 @@
 	model = "STMicroelectronics STM32MP157C eval daughter on eval mother";
 	compatible = "st,stm32mp157c-ev1", "st,stm32mp157c-ed1", "st,stm32mp157";
 
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	aliases {
+		serial0 = &uart4;
+		ethernet0 = &ethernet0;
+	};
+
+	panel_backlight: panel-backlight {
+		compatible = "gpio-backlight";
+		gpios = <&gpiod 13 GPIO_ACTIVE_LOW>;
+		default-on;
+		status = "okay";
+	};
 };
 
 &cec {
@@ -19,12 +34,88 @@
 	status = "okay";
 };
 
+&dsi {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	status = "okay";
+
+	ports {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		port@0 {
+			reg = <0>;
+			dsi_in: endpoint {
+				remote-endpoint = <&ltdc_ep0_out>;
+			};
+		};
+
+		port@1 {
+			reg = <1>;
+			dsi_out: endpoint {
+				remote-endpoint = <&dsi_panel_in>;
+			};
+		};
+	};
+
+	panel-dsi@0 {
+		compatible = "raydium,rm68200";
+		reg = <0>;
+		reset-gpios = <&gpiof 15 GPIO_ACTIVE_LOW>;
+		backlight = <&panel_backlight>;
+		status = "okay";
+
+		port {
+			dsi_panel_in: endpoint {
+				remote-endpoint = <&dsi_out>;
+			};
+		};
+	};
+};
+
+&ethernet0 {
+	status = "okay";
+	pinctrl-0 = <&ethernet0_rgmii_pins_a>;
+	pinctrl-1 = <&ethernet0_rgmii_pins_sleep_a>;
+	pinctrl-names = "default", "sleep";
+	phy-mode = "rgmii";
+	max-speed = <1000>;
+	phy-handle = <&phy0>;
+
+	mdio0 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "snps,dwmac-mdio";
+		phy0: ethernet-phy@0 {
+			reg = <0>;
+		};
+	};
+};
+
 &i2c2 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&i2c2_pins_a>;
 	i2c-scl-rising-time-ns = <185>;
 	i2c-scl-falling-time-ns = <20>;
 	status = "okay";
+
+	stmfx: stmfx@42 {
+		compatible = "st,stmfx-0300";
+		reg = <0x42>;
+		interrupts = <8 IRQ_TYPE_EDGE_RISING>;
+		interrupt-parent = <&gpioi>;
+		vdd-supply = <&v3v3>;
+
+		stmfx_pinctrl: stmfx-pin-controller {
+			compatible = "st,stmfx-0300-pinctrl";
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			gpio-ranges = <&stmfx_pinctrl 0 0 24>;
+			status = "disabled";
+		};
+	};
 };
 
 &i2c5 {
@@ -35,6 +126,26 @@
 	status = "okay";
 };
 
+&ltdc {
+	status = "okay";
+
+	port {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		ltdc_ep0_out: endpoint@0 {
+			reg = <0>;
+			remote-endpoint = <&dsi_in>;
+		};
+	};
+};
+
+&m_can1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&m_can1_pins_a>;
+	status = "okay";
+};
+
 &qspi {
 	pinctrl-names = "default";
 	pinctrl-0 = <&qspi_clk_pins_a &qspi_bk1_pins_a &qspi_bk2_pins_a>;
@@ -60,6 +171,12 @@
 	};
 };
 
+&spi1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi1_pins_a>;
+	status = "disabled";
+};
+
 &timers2 {
 	status = "disabled";
 	pwm {
@@ -106,6 +223,7 @@
 &usbotg_hs {
 	pinctrl-names = "default";
 	pinctrl-0 = <&usbotg_hs_pins_a>;
+	dr_mode = "peripheral";
 	phys = <&usbphyc_port1 0>;
 	phy-names = "usb2-phy";
 	status = "okay";
diff --git a/arch/arm/dts/stm32mp157c.dtsi b/arch/arm/dts/stm32mp157c.dtsi
index 37cadfa..7eb4bee 100644
--- a/arch/arm/dts/stm32mp157c.dtsi
+++ b/arch/arm/dts/stm32mp157c.dtsi
@@ -29,7 +29,7 @@
 	};
 
 	psci {
-		compatible = "arm,psci";
+		compatible = "arm,psci-1.0";
 		method = "smc";
 		cpu_off = <0x84000002>;
 		cpu_on = <0x84000003>;
@@ -106,26 +106,6 @@
 		};
 	};
 
-	pm_domain {
-		#address-cells = <1>;
-		#size-cells = <0>;
-		compatible = "st,stm32mp157c-pd";
-
-		pd_core_ret: core-ret-power-domain@1 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			reg = <1>;
-			#power-domain-cells = <0>;
-			label = "CORE-RETENTION";
-
-			pd_core: core-power-domain@2 {
-				reg = <2>;
-				#power-domain-cells = <0>;
-				label = "CORE";
-			};
-		};
-	};
-
 	soc {
 		compatible = "simple-bus";
 		#address-cells = <1>;
@@ -339,6 +319,34 @@
 			};
 		};
 
+		spi2: spi@4000b000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "st,stm32h7-spi";
+			reg = <0x4000b000 0x400>;
+			interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&rcc SPI2_K>;
+			resets = <&rcc SPI2_R>;
+			dmas = <&dmamux1 39 0x400 0x05>,
+			       <&dmamux1 40 0x400 0x05>;
+			dma-names = "rx", "tx";
+			status = "disabled";
+		};
+
+		spi3: spi@4000c000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "st,stm32h7-spi";
+			reg = <0x4000c000 0x400>;
+			interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&rcc SPI3_K>;
+			resets = <&rcc SPI3_R>;
+			dmas = <&dmamux1 61 0x400 0x05>,
+			       <&dmamux1 62 0x400 0x05>;
+			dma-names = "rx", "tx";
+			status = "disabled";
+		};
+
 		usart2: serial@4000e000 {
 			compatible = "st,stm32h7-uart";
 			reg = <0x4000e000 0x400>;
@@ -522,6 +530,34 @@
 			status = "disabled";
 		};
 
+		spi1: spi@44004000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "st,stm32h7-spi";
+			reg = <0x44004000 0x400>;
+			interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&rcc SPI1_K>;
+			resets = <&rcc SPI1_R>;
+			dmas = <&dmamux1 37 0x400 0x05>,
+			       <&dmamux1 38 0x400 0x05>;
+			dma-names = "rx", "tx";
+			status = "disabled";
+		};
+
+		spi4: spi@44005000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "st,stm32h7-spi";
+			reg = <0x44005000 0x400>;
+			interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&rcc SPI4_K>;
+			resets = <&rcc SPI4_R>;
+			dmas = <&dmamux1 83 0x400 0x05>,
+			       <&dmamux1 84 0x400 0x05>;
+			dma-names = "rx", "tx";
+			status = "disabled";
+		};
+
 		timers15: timer@44006000 {
 			#address-cells = <1>;
 			#size-cells = <0>;
@@ -582,8 +618,118 @@
 				reg = <16>;
 				status = "disabled";
 			};
+		};
+
+		spi5: spi@44009000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "st,stm32h7-spi";
+			reg = <0x44009000 0x400>;
+			interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&rcc SPI5_K>;
+			resets = <&rcc SPI5_R>;
+			dmas = <&dmamux1 85 0x400 0x05>,
+			       <&dmamux1 86 0x400 0x05>;
+			dma-names = "rx", "tx";
+			status = "disabled";
+		};
+
+		dfsdm: dfsdm@4400d000 {
+			compatible = "st,stm32mp1-dfsdm";
+			reg = <0x4400d000 0x800>;
+			clocks = <&rcc DFSDM_K>;
+			clock-names = "dfsdm";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+
+			dfsdm0: filter@0 {
+				compatible = "st,stm32-dfsdm-adc";
+				#io-channel-cells = <1>;
+				reg = <0>;
+				interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
+				dmas = <&dmamux1 101 0x400 0x01>;
+				dma-names = "rx";
+				status = "disabled";
+			};
+
+			dfsdm1: filter@1 {
+				compatible = "st,stm32-dfsdm-adc";
+				#io-channel-cells = <1>;
+				reg = <1>;
+				interrupts = <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
+				dmas = <&dmamux1 102 0x400 0x01>;
+				dma-names = "rx";
+				status = "disabled";
+			};
+
+			dfsdm2: filter@2 {
+				compatible = "st,stm32-dfsdm-adc";
+				#io-channel-cells = <1>;
+				reg = <2>;
+				interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
+				dmas = <&dmamux1 103 0x400 0x01>;
+				dma-names = "rx";
+				status = "disabled";
+			};
+
+			dfsdm3: filter@3 {
+				compatible = "st,stm32-dfsdm-adc";
+				#io-channel-cells = <1>;
+				reg = <3>;
+				interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
+				dmas = <&dmamux1 104 0x400 0x01>;
+				dma-names = "rx";
+				status = "disabled";
+			};
+
+			dfsdm4: filter@4 {
+				compatible = "st,stm32-dfsdm-adc";
+				#io-channel-cells = <1>;
+				reg = <4>;
+				interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>;
+				dmas = <&dmamux1 91 0x400 0x01>;
+				dma-names = "rx";
+				status = "disabled";
+			};
+
+			dfsdm5: filter@5 {
+				compatible = "st,stm32-dfsdm-adc";
+				#io-channel-cells = <1>;
+				reg = <5>;
+				interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
+				dmas = <&dmamux1 92 0x400 0x01>;
+				dma-names = "rx";
+				status = "disabled";
+			};
+		};
+
+		m_can1: can@4400e000 {
+			compatible = "bosch,m_can";
+			reg = <0x4400e000 0x400>, <0x44011000 0x2800>;
+			reg-names = "m_can", "message_ram";
+			interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "int0", "int1";
+			clocks = <&rcc CK_HSE>, <&rcc FDCAN_K>;
+			clock-names = "hclk", "cclk";
+			bosch,mram-cfg = <0x0 0 0 32 0 0 2 2>;
+			status = "disabled";
 		};
 
+		m_can2: can@4400f000 {
+			compatible = "bosch,m_can";
+			reg = <0x4400f000 0x400>, <0x44011000 0x2800>;
+			reg-names = "m_can", "message_ram";
+			interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "int0", "int1";
+			clocks = <&rcc CK_HSE>, <&rcc FDCAN_K>;
+			clock-names = "hclk", "cclk";
+			bosch,mram-cfg = <0x0 0 0 32 0 0 2 2>;
+			status = "disabled";
+		};
+
 		dma1: dma@48000000 {
 			compatible = "st,stm32-dma";
 			reg = <0x48000000 0x400>;
@@ -647,6 +793,8 @@
 				reg = <0x0>;
 				interrupt-parent = <&adc>;
 				interrupts = <0>;
+				dmas = <&dmamux1 9 0x400 0x01>;
+				dma-names = "rx";
 				status = "disabled";
 			};
 
@@ -656,6 +804,8 @@
 				reg = <0x100>;
 				interrupt-parent = <&adc>;
 				interrupts = <1>;
+				dmas = <&dmamux1 10 0x400 0x01>;
+				dma-names = "rx";
 				status = "disabled";
 			};
 		};
@@ -675,7 +825,7 @@
 		};
 
 		usbotg_hs: usb-otg@49000000 {
-			compatible = "st,stm32mp1-hsotg", "snps,dwc2";
+			compatible = "snps,dwc2";
 			reg = <0x49000000 0x10000>;
 			clocks = <&rcc USBO_K>;
 			clock-names = "otg";
@@ -686,7 +836,6 @@
 			g-np-tx-fifo-size = <32>;
 			g-tx-fifo-size = <128 128 64 64 64 64 32 32>;
 			dr_mode = "otg";
-			power-domains = <&pd_core>;
 			status = "disabled";
 		};
 
@@ -753,8 +902,8 @@
 			reg = <0x5000d000 0x400>;
 		};
 
-		syscfg: system-config@50020000 {
-			compatible = "st,stm32-syscfg", "syscon";
+		syscfg: syscon@50020000 {
+			compatible = "st,stm32mp157-syscfg", "syscon";
 			reg = <0x50020000 0x400>;
 		};
 
@@ -853,6 +1002,18 @@
 			status = "disabled";
 		};
 
+		hash1: hash@54002000 {
+			compatible = "st,stm32f756-hash";
+			reg = <0x54002000 0x400>;
+			interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&rcc HASH1>;
+			resets = <&rcc HASH1_R>;
+			dmas = <&mdma1 31 0x10 0x1000A02 0x0 0x0>;
+			dma-names = "in";
+			dma-maxburst = <2>;
+			status = "disabled";
+		};
+
 		rng1: rng@54003000 {
 			compatible = "st,stm32-rng";
 			reg = <0x54003000 0x400>;
@@ -871,7 +1032,7 @@
 			dma-requests = <48>;
 		};
 
-		qspi: qspi@58003000 {
+		qspi: spi@58003000 {
 			compatible = "st,stm32f469-qspi";
 			reg = <0x58003000 0x1000>, <0x70000000 0x10000000>;
 			reg-names = "qspi", "qspi_mm";
@@ -915,6 +1076,36 @@
 			status = "disabled";
 		};
 
+		stmmac_axi_config_0: stmmac-axi-config {
+			snps,wr_osr_lmt = <0x7>;
+			snps,rd_osr_lmt = <0x7>;
+			snps,blen = <0 0 0 0 16 8 4>;
+		};
+
+		ethernet0: ethernet@5800a000 {
+			compatible = "st,stm32mp1-dwmac", "snps,dwmac-4.20a";
+			reg = <0x5800a000 0x2000>;
+			reg-names = "stmmaceth";
+			interrupts-extended = <&intc GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "macirq";
+			clock-names = "stmmaceth",
+				      "mac-clk-tx",
+				      "mac-clk-rx",
+				      "ethstp",
+				      "syscfg-clk";
+			clocks = <&rcc ETHMAC>,
+				 <&rcc ETHTX>,
+				 <&rcc ETHRX>,
+				 <&rcc ETHSTP>,
+				 <&rcc SYSCFG>;
+			st,syscon = <&syscfg 0x4>;
+			snps,mixed-burst;
+			snps,pbl = <2>;
+			snps,axi-config = <&stmmac_axi_config_0>;
+			snps,tso;
+			status = "disabled";
+		};
+
 		usbh_ohci: usbh-ohci@5800c000 {
 			compatible = "generic-ohci";
 			reg = <0x5800c000 0x1000>;
@@ -955,6 +1146,14 @@
 			status = "disabled";
 		};
 
+		iwdg2: watchdog@5a002000 {
+			compatible = "st,stm32mp1-iwdg";
+			reg = <0x5a002000 0x400>;
+			clocks = <&rcc IWDG2>, <&rcc CK_LSI>;
+			clock-names = "pclk", "lsi";
+			status = "disabled";
+		};
+
 		usbphyc: usbphyc@5a006000 {
 			#address-cells = <1>;
 			#size-cells = <0>;
@@ -983,6 +1182,20 @@
 			status = "disabled";
 		};
 
+		spi6: spi@5c001000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "st,stm32h7-spi";
+			reg = <0x5c001000 0x400>;
+			interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&rcc SPI6_K>;
+			resets = <&rcc SPI6_R>;
+			dmas = <&mdma1 34 0x0 0x40008 0x0 0x0>,
+			       <&mdma1 35 0x0 0x40002 0x0 0x0>;
+			dma-names = "rx", "tx";
+			status = "disabled";
+		};
+
 		i2c4: i2c@5c002000 {
 			compatible = "st,stm32f7-i2c";
 			reg = <0x5c002000 0x400>;
@@ -996,6 +1209,22 @@
 			status = "disabled";
 		};
 
+		rtc: rtc@5c004000 {
+			compatible = "st,stm32mp1-rtc";
+			reg = <0x5c004000 0x400>;
+			clocks = <&rcc RTCAPB>, <&rcc RTC>;
+			clock-names = "pclk", "rtc_ck";
+			interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
+			status = "disabled";
+		};
+
+		bsec: nvmem@5c005000 {
+			compatible = "st,stm32mp15-bsec";
+			reg = <0x5c005000 0x400>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+		};
+
 		i2c6: i2c@5c009000 {
 			compatible = "st,stm32f7-i2c";
 			reg = <0x5c009000 0x400>;
diff --git a/arch/arm/dts/stv0991.dts b/arch/arm/dts/stv0991.dts
index 98bd5df..b04e899 100644
--- a/arch/arm/dts/stv0991.dts
+++ b/arch/arm/dts/stv0991.dts
@@ -40,7 +40,7 @@
 			flash0: n25q32@0 {
 				#address-cells = <1>;
 				#size-cells = <1>;
-				compatible = "spi-flash";
+				compatible = "jedec,spi-nor";
 				reg = <0>;		/* chip select */
 				spi-max-frequency = <50000000>;
 				m25p,fast-read;
diff --git a/arch/arm/dts/sun50i-a64-oceanic-5205-5inmfd.dts b/arch/arm/dts/sun50i-a64-oceanic-5205-5inmfd.dts
new file mode 100644
index 0000000..6a21545
--- /dev/null
+++ b/arch/arm/dts/sun50i-a64-oceanic-5205-5inmfd.dts
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2019 Oceanic Systems (UK) Ltd.
+ * Copyright (C) 2019 Amarula Solutions B.V.
+ * Author: Jagan Teki <jagan@amarulasolutions.com>
+ */
+
+/dts-v1/;
+
+#include "sun50i-a64-sopine.dtsi"
+
+/ {
+	model = "Oceanic 5205 5inMFD";
+	compatible = "oceanic,5205-5inmfd", "allwinner,sun50i-a64";
+
+	aliases {
+		ethernet0 = &emac;
+		serial0 = &uart0;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&ehci0 {
+	status = "okay";
+};
+
+&emac {
+	pinctrl-names = "default";
+	pinctrl-0 = <&rgmii_pins>;
+	phy-mode = "rgmii";
+	phy-handle = <&ext_rgmii_phy>;
+	phy-supply = <&reg_dc1sw>;
+	allwinner,tx-delay-ps = <600>;
+	status = "okay";
+};
+
+&mdio {
+	ext_rgmii_phy: ethernet-phy@1 {
+		compatible = "ethernet-phy-ieee802.3-c22";
+		reg = <1>;
+	};
+};
+
+&ohci0 {
+	status = "okay";
+};
+
+&reg_dc1sw {
+	regulator-name = "vcc-phy";
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pb_pins>;
+	status = "okay";
+};
+
+&usb_otg {
+	dr_mode = "host";
+	status = "okay";
+};
+
+&usbphy {
+	status = "okay";
+};
diff --git a/arch/arm/dts/zynq-zed.dts b/arch/arm/dts/zynq-zed.dts
index d2b7fc2..7a540b6 100644
--- a/arch/arm/dts/zynq-zed.dts
+++ b/arch/arm/dts/zynq-zed.dts
@@ -53,7 +53,7 @@
 	status = "okay";
 	num-cs = <1>;
 	flash@0 {
-		compatible = "spansion,s25fl256s", "spi-flash";
+		compatible = "spansion,s25fl256s", "jedec,spi-nor";
 		reg = <0>;
 		spi-max-frequency = <30000000>;
 		m25p,fast-read;
diff --git a/arch/arm/dts/zynqmp-zc1232-revA.dts b/arch/arm/dts/zynqmp-zc1232-revA.dts
index 5c212ba..6117f83 100644
--- a/arch/arm/dts/zynqmp-zc1232-revA.dts
+++ b/arch/arm/dts/zynqmp-zc1232-revA.dts
@@ -41,7 +41,7 @@
 &qspi {
 	status = "okay";
 	flash@0 {
-		compatible = "m25p80", "spi-flash"; /* 32MB FIXME */
+		compatible = "m25p80", "jedec,spi-nor"; /* 32MB FIXME */
 		#address-cells = <1>;
 		#size-cells = <1>;
 		reg = <0x0>;
diff --git a/arch/arm/dts/zynqmp-zc1254-revA.dts b/arch/arm/dts/zynqmp-zc1254-revA.dts
index 881aacc..6ac8346 100644
--- a/arch/arm/dts/zynqmp-zc1254-revA.dts
+++ b/arch/arm/dts/zynqmp-zc1254-revA.dts
@@ -41,7 +41,7 @@
 &qspi {
 	status = "okay";
 	flash@0 {
-		compatible = "m25p80", "spi-flash"; /* 32MB */
+		compatible = "m25p80", "jedec,spi-nor"; /* 32MB */
 		#address-cells = <1>;
 		#size-cells = <1>;
 		reg = <0x0>;
diff --git a/arch/arm/dts/zynqmp-zc1275-revA.dts b/arch/arm/dts/zynqmp-zc1275-revA.dts
index 7403f15..82c30a3 100644
--- a/arch/arm/dts/zynqmp-zc1275-revA.dts
+++ b/arch/arm/dts/zynqmp-zc1275-revA.dts
@@ -41,7 +41,7 @@
 &qspi {
 	status = "okay";
 	flash@0 {
-		compatible = "m25p80", "spi-flash"; /* 32MB */
+		compatible = "m25p80", "jedec,spi-nor"; /* 32MB */
 		#address-cells = <1>;
 		#size-cells = <1>;
 		reg = <0x0>;
diff --git a/arch/arm/dts/zynqmp-zc1275-revB.dts b/arch/arm/dts/zynqmp-zc1275-revB.dts
index 1a7975b..0473503 100644
--- a/arch/arm/dts/zynqmp-zc1275-revB.dts
+++ b/arch/arm/dts/zynqmp-zc1275-revB.dts
@@ -42,7 +42,7 @@
 &qspi {
 	status = "okay";
 	flash@0 {
-		compatible = "m25p80", "spi-flash"; /* 32MB */
+		compatible = "m25p80", "jedec,spi-nor"; /* 32MB */
 		#address-cells = <1>;
 		#size-cells = <1>;
 		reg = <0x0>;
diff --git a/arch/arm/dts/zynqmp-zc1751-xm015-dc1.dts b/arch/arm/dts/zynqmp-zc1751-xm015-dc1.dts
index 9768dfe..8824f5c 100644
--- a/arch/arm/dts/zynqmp-zc1751-xm015-dc1.dts
+++ b/arch/arm/dts/zynqmp-zc1751-xm015-dc1.dts
@@ -101,7 +101,7 @@
 &qspi {
 	status = "okay";
 	flash@0 {
-		compatible = "m25p80", "spi-flash"; /* Micron MT25QU512ABB8ESF */
+		compatible = "m25p80", "jedec,spi-nor"; /* Micron MT25QU512ABB8ESF */
 		#address-cells = <1>;
 		#size-cells = <1>;
 		reg = <0x0>;
diff --git a/arch/arm/dts/zynqmp-zc1751-xm018-dc4.dts b/arch/arm/dts/zynqmp-zc1751-xm018-dc4.dts
index 9afbbb6..84c2904 100644
--- a/arch/arm/dts/zynqmp-zc1751-xm018-dc4.dts
+++ b/arch/arm/dts/zynqmp-zc1751-xm018-dc4.dts
@@ -180,7 +180,7 @@
 &qspi {
 	status = "okay";
 	flash@0 {
-		compatible = "m25p80", "spi-flash"; /* 32MB */
+		compatible = "m25p80", "jedec,spi-nor"; /* 32MB */
 		#address-cells = <1>;
 		#size-cells = <1>;
 		reg = <0x0>;
diff --git a/arch/arm/dts/zynqmp-zcu102-revA.dts b/arch/arm/dts/zynqmp-zcu102-revA.dts
index 0e96a36..6e22871 100644
--- a/arch/arm/dts/zynqmp-zcu102-revA.dts
+++ b/arch/arm/dts/zynqmp-zcu102-revA.dts
@@ -521,7 +521,7 @@
 	status = "okay";
 	is-dual = <1>;
 	flash@0 {
-		compatible = "m25p80", "spi-flash"; /* 32MB */
+		compatible = "m25p80", "jedec,spi-nor"; /* 32MB */
 		#address-cells = <1>;
 		#size-cells = <1>;
 		reg = <0x0>;
diff --git a/arch/arm/dts/zynqmp-zcu104-revA.dts b/arch/arm/dts/zynqmp-zcu104-revA.dts
index 431dff5..c7a3cdc 100644
--- a/arch/arm/dts/zynqmp-zcu104-revA.dts
+++ b/arch/arm/dts/zynqmp-zcu104-revA.dts
@@ -169,7 +169,7 @@
 &qspi {
 	status = "okay";
 	flash@0 {
-		compatible = "m25p80", "spi-flash"; /* n25q512a 128MiB */
+		compatible = "m25p80", "jedec,spi-nor"; /* n25q512a 128MiB */
 		#address-cells = <1>;
 		#size-cells = <1>;
 		reg = <0x0>;
diff --git a/arch/arm/dts/zynqmp-zcu104-revC.dts b/arch/arm/dts/zynqmp-zcu104-revC.dts
index 623d2c9..7df16b0 100644
--- a/arch/arm/dts/zynqmp-zcu104-revC.dts
+++ b/arch/arm/dts/zynqmp-zcu104-revC.dts
@@ -176,7 +176,7 @@
 &qspi {
 	status = "okay";
 	flash@0 {
-		compatible = "m25p80", "spi-flash"; /* n25q512a 128MiB */
+		compatible = "m25p80", "jedec,spi-nor"; /* n25q512a 128MiB */
 		#address-cells = <1>;
 		#size-cells = <1>;
 		reg = <0x0>;
diff --git a/arch/arm/dts/zynqmp-zcu106-revA.dts b/arch/arm/dts/zynqmp-zcu106-revA.dts
index 00f6e30..9fd3953 100644
--- a/arch/arm/dts/zynqmp-zcu106-revA.dts
+++ b/arch/arm/dts/zynqmp-zcu106-revA.dts
@@ -495,7 +495,7 @@
 	status = "okay";
 	is-dual = <1>;
 	flash@0 {
-		compatible = "m25p80", "spi-flash"; /* 32MB */
+		compatible = "m25p80", "jedec,spi-nor"; /* 32MB */
 		#address-cells = <1>;
 		#size-cells = <1>;
 		reg = <0x0>;
diff --git a/arch/arm/dts/zynqmp-zcu111-revA.dts b/arch/arm/dts/zynqmp-zcu111-revA.dts
index 58021be..2e28a39 100644
--- a/arch/arm/dts/zynqmp-zcu111-revA.dts
+++ b/arch/arm/dts/zynqmp-zcu111-revA.dts
@@ -432,7 +432,7 @@
 	status = "okay";
 	is-dual = <1>;
 	flash@0 {
-		compatible = "m25p80", "spi-flash"; /* 32MB */
+		compatible = "m25p80", "jedec,spi-nor"; /* 32MB */
 		#address-cells = <1>;
 		#size-cells = <1>;
 		reg = <0x0>;
diff --git a/arch/arm/include/asm/arch-sunxi/spl.h b/arch/arm/include/asm/arch-sunxi/spl.h
index 4baba38..8c916e8 100644
--- a/arch/arm/include/asm/arch-sunxi/spl.h
+++ b/arch/arm/include/asm/arch-sunxi/spl.h
@@ -28,6 +28,8 @@
 #define SUNXI_BOOTED_FROM_NAND	1
 #define SUNXI_BOOTED_FROM_MMC2	2
 #define SUNXI_BOOTED_FROM_SPI	3
+#define SUNXI_BOOTED_FROM_MMC0_HIGH	0x10
+#define SUNXI_BOOTED_FROM_MMC2_HIGH	0x12
 
 /* boot head definition from sun4i boot code */
 struct boot_file_head {
diff --git a/arch/arm/include/asm/gpio.h b/arch/arm/include/asm/gpio.h
index 3039e66..992a841 100644
--- a/arch/arm/include/asm/gpio.h
+++ b/arch/arm/include/asm/gpio.h
@@ -1,5 +1,6 @@
 #if !defined(CONFIG_ARCH_UNIPHIER) && !defined(CONFIG_ARCH_STI) && \
-	!defined(CONFIG_ARCH_K3)
+	!defined(CONFIG_ARCH_K3) && !defined(CONFIG_ARCH_BCM6858) && \
+	!defined(CONFIG_ARCH_BCM63158)
 #include <asm/arch/gpio.h>
 #endif
 #include <asm-generic/gpio.h>
diff --git a/arch/arm/mach-kirkwood/cpu.c b/arch/arm/mach-kirkwood/cpu.c
index d54de53..8f8e300 100644
--- a/arch/arm/mach-kirkwood/cpu.c
+++ b/arch/arm/mach-kirkwood/cpu.c
@@ -46,69 +46,31 @@
 	return (0x0000ffff & j);
 }
 
-/*
- * kw_config_adr_windows - Configure address Windows
- *
- * There are 8 address windows supported by Kirkwood Soc to addess different
- * devices. Each window can be configured for size, BAR and remap addr
- * Below configuration is standard for most of the cases
- *
- * If remap function not used, remap_lo must be set as base
- *
- * Reference Documentation:
- * Mbus-L to Mbus Bridge Registers Configuration.
- * (Sec 25.1 and 25.3 of Datasheet)
- */
-int kw_config_adr_windows(void)
-{
-	struct kwwin_registers *winregs =
-		(struct kwwin_registers *)KW_CPU_WIN_BASE;
-
+static struct mbus_win windows[] = {
 	/* Window 0: PCIE MEM address space */
-	writel(KWCPU_WIN_CTRL_DATA(1024 * 1024 * 256, KWCPU_TARGET_PCIE,
-		KWCPU_ATTR_PCIE_MEM, KWCPU_WIN_ENABLE), &winregs[0].ctrl);
-
-	writel(KW_DEFADR_PCI_MEM, &winregs[0].base);
-	writel(KW_DEFADR_PCI_MEM, &winregs[0].remap_lo);
-	writel(0x0, &winregs[0].remap_hi);
+	{ KW_DEFADR_PCI_MEM, 1024 * 1024 * 256,
+	  KWCPU_TARGET_PCIE, KWCPU_ATTR_PCIE_MEM },
 
 	/* Window 1: PCIE IO address space */
-	writel(KWCPU_WIN_CTRL_DATA(1024 * 64, KWCPU_TARGET_PCIE,
-		KWCPU_ATTR_PCIE_IO, KWCPU_WIN_ENABLE), &winregs[1].ctrl);
-	writel(KW_DEFADR_PCI_IO, &winregs[1].base);
-	writel(KW_DEFADR_PCI_IO_REMAP, &winregs[1].remap_lo);
-	writel(0x0, &winregs[1].remap_hi);
+	{ KW_DEFADR_PCI_IO, 1024 * 64,
+	  KWCPU_TARGET_PCIE, KWCPU_ATTR_PCIE_IO },
 
 	/* Window 2: NAND Flash address space */
-	writel(KWCPU_WIN_CTRL_DATA(1024 * 1024 * 128, KWCPU_TARGET_MEMORY,
-		KWCPU_ATTR_NANDFLASH, KWCPU_WIN_ENABLE), &winregs[2].ctrl);
-	writel(KW_DEFADR_NANDF, &winregs[2].base);
-	writel(KW_DEFADR_NANDF, &winregs[2].remap_lo);
-	writel(0x0, &winregs[2].remap_hi);
+	{ KW_DEFADR_NANDF, 1024 * 1024 * 128,
+	  KWCPU_TARGET_MEMORY, KWCPU_ATTR_NANDFLASH },
 
 	/* Window 3: SPI Flash address space */
-	writel(KWCPU_WIN_CTRL_DATA(1024 * 1024 * 128, KWCPU_TARGET_MEMORY,
-		KWCPU_ATTR_SPIFLASH, KWCPU_WIN_ENABLE), &winregs[3].ctrl);
-	writel(KW_DEFADR_SPIF, &winregs[3].base);
-	writel(KW_DEFADR_SPIF, &winregs[3].remap_lo);
-	writel(0x0, &winregs[3].remap_hi);
+	{ KW_DEFADR_SPIF, 1024 * 1024 * 128,
+	  KWCPU_TARGET_MEMORY, KWCPU_ATTR_SPIFLASH },
 
 	/* Window 4: BOOT Memory address space */
-	writel(KWCPU_WIN_CTRL_DATA(1024 * 1024 * 128, KWCPU_TARGET_MEMORY,
-		KWCPU_ATTR_BOOTROM, KWCPU_WIN_ENABLE), &winregs[4].ctrl);
-	writel(KW_DEFADR_BOOTROM, &winregs[4].base);
+	{ KW_DEFADR_BOOTROM, 1024 * 1024 * 128,
+	  KWCPU_TARGET_MEMORY, KWCPU_ATTR_BOOTROM },
 
 	/* Window 5: Security SRAM address space */
-	writel(KWCPU_WIN_CTRL_DATA(1024 * 64, KWCPU_TARGET_SASRAM,
-		KWCPU_ATTR_SASRAM, KWCPU_WIN_ENABLE), &winregs[5].ctrl);
-	writel(KW_DEFADR_SASRAM, &winregs[5].base);
-
-	/* Window 6-7: Disabled */
-	writel(KWCPU_WIN_DISABLE, &winregs[6].ctrl);
-	writel(KWCPU_WIN_DISABLE, &winregs[7].ctrl);
-
-	return 0;
-}
+	{ KW_DEFADR_SASRAM, 1024 * 64,
+	  KWCPU_TARGET_SASRAM, KWCPU_ATTR_SASRAM },
+};
 
 /*
  * SYSRSTn Duration Counter Support
@@ -221,15 +183,13 @@
 	struct kwcpu_registers *cpureg =
 		(struct kwcpu_registers *)KW_CPU_REG_BASE;
 
-	/* Linux expects` the internal registers to be at 0xf1000000 */
+	/* Linux expects the internal registers to be at 0xf1000000 */
 	writel(KW_REGS_PHY_BASE, KW_OFFSET_REG);
 
 	/* Enable and invalidate L2 cache in write through mode */
 	writel(readl(&cpureg->l2_cfg) | 0x18, &cpureg->l2_cfg);
 	invalidate_l2_cache();
 
-	kw_config_adr_windows();
-
 #ifdef CONFIG_KIRKWOOD_RGMII_PAD_1V8
 	/*
 	 * Configures the I/O voltage of the pads connected to Egigabit
@@ -291,11 +251,13 @@
 	temp |= (1 << 22);
 	writefr_extra_feature_reg(temp);
 
-	icache_enable();
 	/* Change reset vector to address 0x0 */
 	temp = get_cr();
 	set_cr(temp & ~CR_V);
 
+	/* Configure mbus windows */
+	mvebu_mbus_probe(windows, ARRAY_SIZE(windows));
+
 	/* checks and execute resset to factory event */
 	kw_sysrst_check();
 
diff --git a/arch/arm/mach-kirkwood/include/mach/cpu.h b/arch/arm/mach-kirkwood/include/mach/cpu.h
index 91d2151..ea42182 100644
--- a/arch/arm/mach-kirkwood/include/mach/cpu.h
+++ b/arch/arm/mach-kirkwood/include/mach/cpu.h
@@ -63,12 +63,18 @@
  */
 #define KW_DEFADR_PCI_MEM	0x90000000
 #define KW_DEFADR_PCI_IO	0xC0000000
-#define KW_DEFADR_PCI_IO_REMAP	0xC0000000
 #define KW_DEFADR_SASRAM	0xC8010000
 #define KW_DEFADR_NANDF		0xD8000000
 #define KW_DEFADR_SPIF		0xE8000000
 #define KW_DEFADR_BOOTROM	0xF8000000
 
+struct mbus_win {
+	u32 base;
+	u32 size;
+	u8 target;
+	u8 attr;
+};
+
 /*
  * read feroceon/sheeva core extra feature register
  * using co-proc instruction
@@ -135,13 +141,16 @@
 	u32 irq_level;
 };
 
+/* Needed for dynamic (board-specific) mbus configuration */
+extern struct mvebu_mbus_state mbus_state;
+
 /*
  * functions
  */
 unsigned int mvebu_sdram_bar(enum memory_bank bank);
 unsigned int mvebu_sdram_bs(enum memory_bank bank);
 void mvebu_sdram_size_adjust(enum memory_bank bank);
-int kw_config_adr_windows(void);
+int mvebu_mbus_probe(struct mbus_win windows[], int count);
 void mvebu_config_gpio(unsigned int gpp0_oe_val, unsigned int gpp1_oe_val,
 		unsigned int gpp0_oe, unsigned int gpp1_oe);
 int kw_config_mpp(unsigned int mpp0_7, unsigned int mpp8_15,
diff --git a/arch/arm/mach-kirkwood/include/mach/soc.h b/arch/arm/mach-kirkwood/include/mach/soc.h
index 227707a..1d7f282 100644
--- a/arch/arm/mach-kirkwood/include/mach/soc.h
+++ b/arch/arm/mach-kirkwood/include/mach/soc.h
@@ -31,7 +31,7 @@
 #define KW_RTC_BASE			(KW_REGISTER(0x10300))
 #define KW_NANDF_BASE			(KW_REGISTER(0x10418))
 #define MVEBU_SPI_BASE			(KW_REGISTER(0x10600))
-#define KW_CPU_WIN_BASE			(KW_REGISTER(0x20000))
+#define MVEBU_CPU_WIN_BASE			(KW_REGISTER(0x20000))
 #define KW_CPU_REG_BASE			(KW_REGISTER(0x20100))
 #define MVEBU_TIMER_BASE			(KW_REGISTER(0x20300))
 #define KW_REG_PCIE_BASE		(KW_REGISTER(0x40000))
diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
index 7dda04e..f5fd60d 100644
--- a/arch/arm/mach-mvebu/Kconfig
+++ b/arch/arm/mach-mvebu/Kconfig
@@ -9,10 +9,10 @@
 	select ARCH_MISC_INIT
 	select BOARD_EARLY_INIT_F
 	select CPU_V7A
-	select SPL_DM
-	select SPL_DM_SEQ_ALIAS
-	select SPL_OF_CONTROL
-	select SPL_SIMPLE_BUS
+	select SPL_DM if SPL
+	select SPL_DM_SEQ_ALIAS if SPL
+	select SPL_OF_CONTROL if SPL
+	select SPL_SIMPLE_BUS if SPL
 	select SUPPORT_SPL
 
 config ARMADA_64BIT
@@ -46,7 +46,7 @@
 # Armada PLL frequency (used for NAND clock generation)
 config SYS_MVEBU_PLL_CLOCK
 	int
-	default "2000000000" if ARMADA_XP || ARMADA_3700 || ARMADA_8K
+	default "2000000000" if ARMADA_XP || ARMADA_3700 || ARMADA_8K || ARMADA_MSYS
 	default "1000000000" if ARMADA_38X || ARMADA_375
 
 # Armada XP/38x SoC types...
@@ -63,6 +63,22 @@
 	bool
 	select ARMADA_XP
 
+config ARMADA_MSYS
+	bool
+	select ARMADA_32BIT
+
+config 98DX4251
+	bool
+	select ARMADA_MSYS
+
+config 98DX3336
+	bool
+	select ARMADA_MSYS
+
+config 98DX3236
+	bool
+	select ARMADA_MSYS
+
 config 88F6820
 	bool
 	select ARMADA_38X
@@ -136,6 +152,10 @@
 	bool "Support Allied Telesis x530"
 	select 88F6820
 
+config TARGET_DB_XC3_24G4XG
+	bool "Support DB-XC3-24G4XG"
+	select 98DX3336
+
 endchoice
 
 config SYS_BOARD
@@ -154,6 +174,7 @@
 	default "theadorable" if TARGET_THEADORABLE
 	default "a38x" if TARGET_CONTROLCENTERDC
 	default "x530" if TARGET_X530
+	default "db-xc3-24g4xg" if TARGET_DB_XC3_24G4XG
 
 config SYS_CONFIG_NAME
 	default "clearfog" if TARGET_CLEARFOG
@@ -171,6 +192,7 @@
 	default "turris_mox" if TARGET_TURRIS_MOX
 	default "controlcenterdc" if TARGET_CONTROLCENTERDC
 	default "x530" if TARGET_X530
+	default "db-xc3-24g4xg" if TARGET_DB_XC3_24G4XG
 
 config SYS_VENDOR
 	default "Marvell" if TARGET_DB_MV784MP_GP
@@ -179,6 +201,8 @@
 	default "Marvell" if TARGET_DB_88F6820_GP
 	default "Marvell" if TARGET_DB_88F6820_AMC
 	default "Marvell" if TARGET_MVEBU_ARMADA_8K
+	default "Marvell" if TARGET_DB_XC3_24G4XG
+	default "Marvell" if TARGET_MVEBU_DB_88F7040
 	default "solidrun" if TARGET_CLEARFOG
 	default "kobol" if TARGET_HELIOS4
 	default "Synology" if TARGET_DS414
diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile
index ee2eca9..02d3ce2 100644
--- a/arch/arm/mach-mvebu/Makefile
+++ b/arch/arm/mach-mvebu/Makefile
@@ -14,6 +14,7 @@
 
 obj-y	= dram.o
 obj-y	+= gpio.o
+obj-y	+= mbus.o
 obj-y	+= timer.o
 
 else # CONFIG_KIRKWOOD
@@ -24,6 +25,7 @@
 obj-$(CONFIG_ARMADA_375) += ../../../drivers/ddr/marvell/axp/xor.o
 obj-$(CONFIG_ARMADA_38X) += ../../../drivers/ddr/marvell/a38x/xor.o
 obj-$(CONFIG_ARMADA_XP) += ../../../drivers/ddr/marvell/axp/xor.o
+obj-$(CONFIG_ARMADA_MSYS) += ../../../drivers/ddr/marvell/axp/xor.o
 obj-$(CONFIG_MVEBU_EFUSE) += efuse.o
 
 extra-y += kwbimage.cfg
diff --git a/arch/arm/mach-mvebu/cpu.c b/arch/arm/mach-mvebu/cpu.c
index 919d05c..c5b3df4 100644
--- a/arch/arm/mach-mvebu/cpu.c
+++ b/arch/arm/mach-mvebu/cpu.c
@@ -23,6 +23,11 @@
 	/* NOR */
 	{ MBUS_BOOTROM_BASE, MBUS_BOOTROM_SIZE,
 	  CPU_TARGET_DEVICEBUS_BOOTROM_SPI, CPU_ATTR_BOOTROM },
+
+#ifdef CONFIG_ARMADA_MSYS
+	/* DFX */
+	{ MBUS_DFX_BASE, MBUS_DFX_SIZE, CPU_TARGET_DFX, 0 },
+#endif
 };
 
 void lowlevel_init(void)
@@ -121,6 +126,14 @@
 	{ 0x13,  0x0, 2000, 1000, 933 },
 	{ 0xff, 0xff,    0,    0,   0 }	/* 0xff marks end of array */
 };
+#elif defined(CONFIG_ARMADA_MSYS)
+static const struct sar_freq_modes sar_freq_tab[] = {
+	{  0x0,	0x0,  400,  400, 400 },
+	{  0x2, 0x0,  667,  333, 667 },
+	{  0x3, 0x0,  800,  400, 800 },
+	{  0x5, 0x0,  800,  400, 800 },
+	{ 0xff, 0xff,    0,   0,   0 }	/* 0xff marks end of array */
+};
 #else
 /* SAR frequency values for Armada XP */
 static const struct sar_freq_modes sar_freq_tab[] = {
@@ -144,7 +157,7 @@
 	u32 freq;
 	int i;
 
-#if defined(CONFIG_ARMADA_375)
+#if defined(CONFIG_ARMADA_375) || defined(CONFIG_ARMADA_MSYS)
 	val = readl(CONFIG_SAR2_REG);	/* SAR - Sample At Reset */
 #else
 	val = readl(CONFIG_SAR_REG);	/* SAR - Sample At Reset */
@@ -160,7 +173,7 @@
 #endif
 	for (i = 0; sar_freq_tab[i].val != 0xff; i++) {
 		if (sar_freq_tab[i].val == freq) {
-#if defined(CONFIG_ARMADA_375) || defined(CONFIG_ARMADA_38X)
+#if defined(CONFIG_ARMADA_375) || defined(CONFIG_ARMADA_38X) || defined(CONFIG_ARMADA_MSYS)
 			*sar_freq = sar_freq_tab[i];
 			return;
 #else
@@ -270,6 +283,20 @@
 		}
 	}
 
+	if (mvebu_soc_family() == MVEBU_SOC_MSYS) {
+		switch (revid) {
+		case 3:
+			puts("A0");
+			break;
+		case 4:
+			puts("A1");
+			break;
+		default:
+			printf("?? (%x)", revid);
+			break;
+		}
+	}
+
 	get_sar_freq(&sar_freq);
 	printf(" at %d MHz\n", sar_freq.p_clk);
 
@@ -472,6 +499,8 @@
 
 	if (mvebu_soc_family() == MVEBU_SOC_A38X)
 		reg = MVEBU_DFX_DIV_CLK_CTRL(1);
+	else if (mvebu_soc_family() == MVEBU_SOC_MSYS)
+		reg = MVEBU_DFX_DIV_CLK_CTRL(8);
 	else
 		reg = MVEBU_CORE_DIV_CLK_CTRL(1);
 
@@ -501,7 +530,6 @@
 }
 #endif
 
-#ifdef CONFIG_SCSI_AHCI_PLAT
 #define AHCI_VENDOR_SPECIFIC_0_ADDR	0xa0
 #define AHCI_VENDOR_SPECIFIC_0_DATA	0xa4
 
@@ -545,11 +573,19 @@
 	writel(0x80, base + AHCI_VENDOR_SPECIFIC_0_DATA);
 }
 
-void scsi_init(void)
+int board_ahci_enable(void)
 {
-	printf("MVEBU SATA INIT\n");
 	ahci_mvebu_mbus_config((void __iomem *)MVEBU_SATA0_BASE);
 	ahci_mvebu_regret_option((void __iomem *)MVEBU_SATA0_BASE);
+
+	return 0;
+}
+
+#ifdef CONFIG_SCSI_AHCI_PLAT
+void scsi_init(void)
+{
+	printf("MVEBU SATA INIT\n");
+	board_ahci_enable();
 	ahci_init((void __iomem *)MVEBU_SATA0_BASE);
 }
 #endif
diff --git a/arch/arm/mach-mvebu/include/mach/config.h b/arch/arm/mach-mvebu/include/mach/config.h
index 71c4f70..bbcfcfd 100644
--- a/arch/arm/mach-mvebu/include/mach/config.h
+++ b/arch/arm/mach-mvebu/include/mach/config.h
@@ -17,7 +17,7 @@
 #include <asm/arch/soc.h>
 
 #if defined(CONFIG_ARMADA_XP) || defined(CONFIG_ARMADA_375) \
-	|| defined(CONFIG_ARMADA_38X)
+	|| defined(CONFIG_ARMADA_38X) || defined(CONFIG_ARMADA_MSYS)
 /*
  * Set this for the common xor register definitions needed in dram.c
  * for A38x as well here.
diff --git a/arch/arm/mach-mvebu/include/mach/cpu.h b/arch/arm/mach-mvebu/include/mach/cpu.h
index 9e23043..b9153d8 100644
--- a/arch/arm/mach-mvebu/include/mach/cpu.h
+++ b/arch/arm/mach-mvebu/include/mach/cpu.h
@@ -34,6 +34,7 @@
 	CPU_TARGET_PCIE02 = 0x4,
 	CPU_TARGET_ETH01 = 0x7,
 	CPU_TARGET_PCIE13 = 0x8,
+	CPU_TARGET_DFX = 0x8,
 	CPU_TARGET_SASRAM = 0x9,
 	CPU_TARGET_SATA01 = 0xa, /* A38X */
 	CPU_TARGET_NAND = 0xd,
@@ -79,6 +80,8 @@
 #define MBUS_PCI_IO_SIZE	(64 << 10)
 #define MBUS_SPI_BASE		0xF4000000
 #define MBUS_SPI_SIZE		(8 << 20)
+#define MBUS_DFX_BASE		0xF6000000
+#define MBUS_DFX_SIZE		(1 << 20)
 #define MBUS_BOOTROM_BASE	0xF8000000
 #define MBUS_BOOTROM_SIZE	(8 << 20)
 
diff --git a/arch/arm/mach-mvebu/include/mach/soc.h b/arch/arm/mach-mvebu/include/mach/soc.h
index 01577f4..f666ee2 100644
--- a/arch/arm/mach-mvebu/include/mach/soc.h
+++ b/arch/arm/mach-mvebu/include/mach/soc.h
@@ -76,7 +76,11 @@
 #define MVEBU_NAND_BASE		(MVEBU_REGISTER(0xd0000))
 #define MVEBU_SDIO_BASE		(MVEBU_REGISTER(0xd8000))
 #define MVEBU_LCD_BASE		(MVEBU_REGISTER(0xe0000))
+#ifdef CONFIG_ARMADA_MSYS
+#define MVEBU_DFX_BASE		(MBUS_DFX_BASE)
+#else
 #define MVEBU_DFX_BASE		(MVEBU_REGISTER(0xe4000))
+#endif
 
 #define SOC_COHERENCY_FABRIC_CTRL_REG	(MVEBU_REGISTER(0x20200))
 #define MBUS_ERR_PROP_EN	(1 << 8)
@@ -96,9 +100,20 @@
 #define SPI_PUP_EN		BIT(5)
 
 #define MVEBU_CORE_DIV_CLK_CTRL(i)	(MVEBU_CLOCK_BASE + ((i) * 0x8))
+#ifdef CONFIG_ARMADA_MSYS
+#define MVEBU_DFX_DIV_CLK_CTRL(i)	(MVEBU_DFX_BASE + 0xf8000 + 0x250 + ((i) * 0x4))
+#define NAND_ECC_DIVCKL_RATIO_OFFS	6
+#define NAND_ECC_DIVCKL_RATIO_MASK	(0xF << NAND_ECC_DIVCKL_RATIO_OFFS)
+#else
 #define MVEBU_DFX_DIV_CLK_CTRL(i)	(MVEBU_DFX_BASE + 0x250 + ((i) * 0x4))
+#endif
+#ifdef CONFIG_ARMADA_MSYS
+#define NAND_ECC_DIVCKL_RATIO_OFFS	6
+#define NAND_ECC_DIVCKL_RATIO_MASK	(0xF << NAND_ECC_DIVCKL_RATIO_OFFS)
+#else
 #define NAND_ECC_DIVCKL_RATIO_OFFS	8
 #define NAND_ECC_DIVCKL_RATIO_MASK	(0x3F << NAND_ECC_DIVCKL_RATIO_OFFS)
+#endif
 
 #define SDRAM_MAX_CS		4
 #define SDRAM_ADDR_MASK		0xFF000000
@@ -149,6 +164,22 @@
 #define BOOT_FROM_SPI		0x32
 #define BOOT_FROM_MMC		0x30
 #define BOOT_FROM_MMC_ALT	0x31
+#elif defined(CONFIG_ARMADA_MSYS)
+/* SAR values for MSYS */
+#define CONFIG_SAR_REG		(MBUS_DFX_BASE  + 0xf8200)
+#define CONFIG_SAR2_REG		(MBUS_DFX_BASE  + 0xf8204)
+
+#define SAR_CPU_FREQ_OFFS	18
+#define SAR_CPU_FREQ_MASK	(0x7 << SAR_CPU_FREQ_OFFS)
+#define SAR_BOOT_DEVICE_OFFS	11
+#define SAR_BOOT_DEVICE_MASK	(0x7 << SAR_BOOT_DEVICE_OFFS)
+
+#define BOOT_DEV_SEL_OFFS	11
+#define BOOT_DEV_SEL_MASK	(0x7 << BOOT_DEV_SEL_OFFS)
+
+#define BOOT_FROM_NAND		0x1
+#define BOOT_FROM_UART		0x2
+#define BOOT_FROM_SPI		0x3
 #else
 /* SAR values for Armada XP */
 #define CONFIG_SAR_REG		(MVEBU_REGISTER(0x18230))
diff --git a/arch/arm/mach-mvebu/mbus.c b/arch/arm/mach-mvebu/mbus.c
index df4c5cb..c68e93b 100644
--- a/arch/arm/mach-mvebu/mbus.c
+++ b/arch/arm/mach-mvebu/mbus.c
@@ -344,6 +344,11 @@
 		}
 	}
 	mbus_dram_info.num_cs = cs;
+
+#if defined(CONFIG_ARMADA_MSYS)
+	/* Disable MBUS Err Prop - in order to avoid data aborts */
+	clrbits_le32(mbus->mbuswins_base + 0x200, BIT(8));
+#endif
 }
 
 static const struct mvebu_mbus_soc_data
@@ -405,6 +410,7 @@
 	return 0;
 }
 
+#ifndef CONFIG_KIRKWOOD
 static void mvebu_mbus_get_lowest_base(struct mvebu_mbus_state *mbus,
 				       phys_addr_t *base)
 {
@@ -451,6 +457,7 @@
 	val = (size / (64 << 10)) - 1;
 	writel((val << 16) | 0x1, MBUS_BRIDGE_WIN_CTRL_REG);
 }
+#endif
 
 int mbus_dt_setup_win(struct mvebu_mbus_state *mbus,
 		      u32 base, u32 size, u8 target, u8 attr)
@@ -471,12 +478,14 @@
 			return -ENOMEM;
 	}
 
+#ifndef CONFIG_KIRKWOOD
 	/*
 	 * Re-configure the mbus bridge registers each time this function
 	 * is called. Since it may get called from the board code in
 	 * later boot stages as well.
 	 */
 	mvebu_config_mbus_bridge(mbus);
+#endif
 
 	return 0;
 }
diff --git a/arch/arm/mach-mvebu/serdes/axp/high_speed_env_lib.c b/arch/arm/mach-mvebu/serdes/axp/high_speed_env_lib.c
index 569840f..c8c9298 100644
--- a/arch/arm/mach-mvebu/serdes/axp/high_speed_env_lib.c
+++ b/arch/arm/mach-mvebu/serdes/axp/high_speed_env_lib.c
@@ -35,7 +35,7 @@
 #define	ETM_MODULE_DETECT               2
 
 #define PEX_MODE_GET(satr)		((satr & 0x6) >> 1)
-#define PEX_CAPABILITY_GET(satr)	(satr & 1)
+#define PEX_CAPABILITY_GET(satr, port)	((satr >> port) & 1)
 #define MV_PEX_UNIT_TO_IF(pex_unit)	((pex_unit < 3) ? (pex_unit * 4) : 9)
 
 /* Static parametes */
@@ -176,7 +176,7 @@
 	return ((sar_msb & 0x100000) >> 17) | ((sar & 0xe00000) >> 21);
 }
 
-__weak MV_BIN_SERDES_CFG *board_serdes_cfg_get(u8 pex_mode)
+__weak MV_BIN_SERDES_CFG *board_serdes_cfg_get(void)
 {
 	u32 board_id;
 	u32 serdes_cfg_val = 0;	/* default */
@@ -352,7 +352,7 @@
 		DEBUG_WR_REG(CPU_AVS_CONTROL2_REG, cpu_avs);
 	}
 
-	info = board_serdes_cfg_get(PEX_MODE_GET(satr11));
+	info = board_serdes_cfg_get();
 
 	if (info == NULL) {
 		DEBUG_INIT_S("Hight speed PHY Error #1\n");
@@ -675,7 +675,7 @@
 				tmp |= (0x1 << 4);
 			if (info->pex_mode[pex_unit] == PEX_BUS_MODE_X4)
 				tmp |= (0x4 << 4);
-			if (0 == PEX_CAPABILITY_GET(satr11))
+			if (0 == PEX_CAPABILITY_GET(satr11, pex_unit))
 				tmp |= 0x1;
 			else
 				tmp |= 0x2;
diff --git a/arch/arm/mach-stm32mp/Kconfig b/arch/arm/mach-stm32mp/Kconfig
index 8a929fa..73aa382 100644
--- a/arch/arm/mach-stm32mp/Kconfig
+++ b/arch/arm/mach-stm32mp/Kconfig
@@ -17,7 +17,7 @@
 	select SPL_DM_RESET
 	select SPL_SERIAL_SUPPORT
 	select SPL_SYSCON
-	select SPL_DRIVERS_MISC_SUPPORT
+	imply SPL_DISPLAY_PRINT
 	imply SPL_LIBDISK_SUPPORT
 
 config SYS_SOC
@@ -25,18 +25,31 @@
 
 config TARGET_STM32MP1
 	bool "Support stm32mp1xx"
-	select ARCH_SUPPORT_PSCI
+	select ARCH_SUPPORT_PSCI if !STM32MP1_TRUSTED
 	select CPU_V7A
-	select CPU_V7_HAS_NONSEC
+	select CPU_V7_HAS_NONSEC if !STM32MP1_TRUSTED
 	select CPU_V7_HAS_VIRT
 	select PINCTRL_STM32
 	select STM32_RCC
 	select STM32_RESET
 	select SYS_ARCH_TIMER
-	select SYSRESET_SYSCON
+	imply SYSRESET_PSCI if STM32MP1_TRUSTED
+	imply SYSRESET_SYSCON if !STM32MP1_TRUSTED
 	help
 		target STMicroelectronics SOC STM32MP1 family
+		STM32MP157, STM32MP153 or STM32MP151
 		STMicroelectronics MPU with core ARMv7
+		dual core A7 for STM32MP157/3, monocore for STM32MP151
+
+config STM32MP1_TRUSTED
+	bool "Support trusted boot with TF-A"
+	default y if !SPL
+	select ARM_SMCCC
+	help
+		Say Y here to enable boot with TF-A
+		Trusted boot chain is :
+		BootRom => TF-A.stm32 (clock & DDR) => U-Boot.stm32
+		TF-A monitor provides proprietary smc to manage secure devices
 
 config SYS_TEXT_BASE
 	prompt "U-Boot base address"
@@ -46,6 +59,9 @@
 		when DDR driver is used:
 		  DDR + 1MB (0xC0100000)
 
+config NR_DRAM_BANKS
+	default 1
+
 config SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION_MMC2
 	hex "Partition on MMC2 to use to load U-Boot from"
 	depends on SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION
@@ -54,9 +70,6 @@
 	  Partition on the second MMC to load U-Boot from when the MMC is being
 	  used in raw mode
 
-source "board/st/stm32mp1/Kconfig"
-
-# currently activated for debug / should be deactivated for real product
 if DEBUG_UART
 
 config DEBUG_UART_BOARD_INIT
@@ -71,4 +84,6 @@
 	default 64000000
 endif
 
+source "board/st/stm32mp1/Kconfig"
+
 endif
diff --git a/arch/arm/mach-stm32mp/Makefile b/arch/arm/mach-stm32mp/Makefile
index f59ced5..1493914 100644
--- a/arch/arm/mach-stm32mp/Makefile
+++ b/arch/arm/mach-stm32mp/Makefile
@@ -11,6 +11,9 @@
 obj-y += spl.o
 else
 obj-y += bsec.o
+ifndef CONFIG_STM32MP1_TRUSTED
+obj-$(CONFIG_SYSRESET) += cmd_poweroff.o
+endif
 endif
 obj-$(CONFIG_ARMV7_PSCI) += psci.o
 obj-$(CONFIG_$(SPL_)DM_REGULATOR) += pwr_regulator.o
diff --git a/arch/arm/mach-stm32mp/bsec.c b/arch/arm/mach-stm32mp/bsec.c
index d087a31..9ed8d8c 100644
--- a/arch/arm/mach-stm32mp/bsec.c
+++ b/arch/arm/mach-stm32mp/bsec.c
@@ -8,9 +8,12 @@
 #include <misc.h>
 #include <asm/io.h>
 #include <linux/iopoll.h>
+#include <asm/arch/stm32mp1_smc.h>
+#include <linux/arm-smccc.h>
 
 #define BSEC_OTP_MAX_VALUE		95
 
+#ifndef CONFIG_STM32MP1_TRUSTED
 #define BSEC_TIMEOUT_US			10000
 
 /* BSEC REGISTER OFFSET (base relative) */
@@ -168,7 +171,7 @@
 		ret = bsec_power_safmem(base, true);
 		if (ret)
 			return ret;
-		power_up = 1;
+		power_up = true;
 	}
 	/* set BSEC_OTP_CTRL_OFF with the otp value*/
 	writel(otp | BSEC_READ, base + BSEC_OTP_CTRL_OFF);
@@ -270,6 +273,7 @@
 
 	return ret;
 }
+#endif /* CONFIG_STM32MP1_TRUSTED */
 
 /* BSEC MISC driver *******************************************************/
 struct stm32mp_bsec_platdata {
@@ -278,6 +282,11 @@
 
 static int stm32mp_bsec_read_otp(struct udevice *dev, u32 *val, u32 otp)
 {
+#ifdef CONFIG_STM32MP1_TRUSTED
+	return stm32_smc(STM32_SMC_BSEC,
+			 STM32_SMC_READ_OTP,
+			 otp, 0, val);
+#else
 	struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev);
 	u32 tmp_data = 0;
 	int ret;
@@ -299,27 +308,46 @@
 	/* restore shadow value */
 	ret = bsec_write_shadow(plat->base, tmp_data, otp);
 	return ret;
+#endif
 }
 
 static int stm32mp_bsec_read_shadow(struct udevice *dev, u32 *val, u32 otp)
 {
+#ifdef CONFIG_STM32MP1_TRUSTED
+	return stm32_smc(STM32_SMC_BSEC,
+			 STM32_SMC_READ_SHADOW,
+			 otp, 0, val);
+#else
 	struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev);
 
 	return bsec_read_shadow(plat->base, val, otp);
+#endif
 }
 
 static int stm32mp_bsec_write_otp(struct udevice *dev, u32 val, u32 otp)
 {
+#ifdef CONFIG_STM32MP1_TRUSTED
+	return stm32_smc_exec(STM32_SMC_BSEC,
+			      STM32_SMC_PROG_OTP,
+			      otp, val);
+#else
 	struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev);
 
 	return bsec_program_otp(plat->base, val, otp);
+#endif
 }
 
 static int stm32mp_bsec_write_shadow(struct udevice *dev, u32 val, u32 otp)
 {
+#ifdef CONFIG_STM32MP1_TRUSTED
+	return stm32_smc_exec(STM32_SMC_BSEC,
+			      STM32_SMC_WRITE_SHADOW,
+			      otp, val);
+#else
 	struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev);
 
 	return bsec_write_shadow(plat->base, val, otp);
+#endif
 }
 
 static int stm32mp_bsec_read(struct udevice *dev, int offset,
@@ -404,9 +432,24 @@
 
 	return 0;
 }
+
+#ifndef CONFIG_STM32MP1_TRUSTED
+static int stm32mp_bsec_probe(struct udevice *dev)
+{
+	int otp;
+	struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev);
+
+	/* update unlocked shadow for OTP cleared by the rom code */
+	for (otp = 57; otp <= BSEC_OTP_MAX_VALUE; otp++)
+		if (!bsec_read_SR_lock(plat->base, otp))
+			bsec_shadow_register(plat->base, otp);
+
+	return 0;
+}
+#endif
 
 static const struct udevice_id stm32mp_bsec_ids[] = {
-	{ .compatible = "st,stm32mp-bsec" },
+	{ .compatible = "st,stm32mp15-bsec" },
 	{}
 };
 
@@ -417,14 +460,7 @@
 	.ofdata_to_platdata = stm32mp_bsec_ofdata_to_platdata,
 	.platdata_auto_alloc_size = sizeof(struct stm32mp_bsec_platdata),
 	.ops = &stm32mp_bsec_ops,
-};
-
-/* bsec IP is not present in device tee, manage IP address by platdata */
-static struct stm32mp_bsec_platdata stm32_bsec_platdata = {
-	.base = STM32_BSEC_BASE,
-};
-
-U_BOOT_DEVICE(stm32mp_bsec) = {
-	.name = "stm32mp_bsec",
-	.platdata = &stm32_bsec_platdata,
+#ifndef CONFIG_STM32MP1_TRUSTED
+	.probe = stm32mp_bsec_probe,
+#endif
 };
diff --git a/arch/arm/mach-stm32mp/cmd_poweroff.c b/arch/arm/mach-stm32mp/cmd_poweroff.c
new file mode 100644
index 0000000..f54dd1d
--- /dev/null
+++ b/arch/arm/mach-stm32mp/cmd_poweroff.c
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) 2019, STMicroelectronics - All Rights Reserved
+ */
+
+#include <common.h>
+#include <command.h>
+#include <sysreset.h>
+
+int do_poweroff(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	int ret;
+
+	puts("poweroff ...\n");
+	mdelay(100);
+
+	ret = sysreset_walk(SYSRESET_POWER);
+
+	if (ret == -EINPROGRESS)
+		mdelay(1000);
+
+	/*NOTREACHED when power off*/
+	return CMD_RET_FAILURE;
+}
diff --git a/arch/arm/mach-stm32mp/config.mk b/arch/arm/mach-stm32mp/config.mk
index f371aac..403af2a 100644
--- a/arch/arm/mach-stm32mp/config.mk
+++ b/arch/arm/mach-stm32mp/config.mk
@@ -3,7 +3,20 @@
 # Copyright (C) 2018, STMicroelectronics - All Rights Reserved
 #
 
-ALL-$(CONFIG_SPL_BUILD) += u-boot-spl.stm32
+ifndef CONFIG_SPL
+ALL-y += u-boot.stm32
+else
+ifdef CONFIG_SPL_BUILD
+ALL-y += u-boot-spl.stm32
+endif
+endif
+
+MKIMAGEFLAGS_u-boot.stm32 = -T stm32image -a $(CONFIG_SYS_TEXT_BASE) -e $(CONFIG_SYS_TEXT_BASE)
+
+u-boot.stm32: MKIMAGEOUTPUT = u-boot.stm32.log
+
+u-boot.stm32: u-boot.bin FORCE
+	$(call if_changed,mkimage)
 
 MKIMAGEFLAGS_u-boot-spl.stm32 = -T stm32image -a $(CONFIG_SPL_TEXT_BASE) -e $(CONFIG_SPL_TEXT_BASE)
 
diff --git a/arch/arm/mach-stm32mp/cpu.c b/arch/arm/mach-stm32mp/cpu.c
index b893358..7b4431c 100644
--- a/arch/arm/mach-stm32mp/cpu.c
+++ b/arch/arm/mach-stm32mp/cpu.c
@@ -18,6 +18,7 @@
 #define RCC_DBGCFGR		(STM32_RCC_BASE + 0x080C)
 #define RCC_BDCR		(STM32_RCC_BASE + 0x0140)
 #define RCC_MP_APB5ENSETR	(STM32_RCC_BASE + 0x0208)
+#define RCC_MP_AHB5ENSETR	(STM32_RCC_BASE + 0x0210)
 #define RCC_BDCR_VSWRST		BIT(31)
 #define RCC_BDCR_RTCSRC		GENMASK(17, 16)
 #define RCC_DBGCFGR_DBGCKEN	BIT(8)
@@ -44,6 +45,9 @@
 #define DBGMCU_IDC_REV_ID_MASK	GENMASK(31, 16)
 #define DBGMCU_IDC_REV_ID_SHIFT	16
 
+/* GPIOZ registers */
+#define GPIOZ_SECCFGR		0x54004030
+
 /* boot interface from Bootrom
  * - boot instance = bit 31:16
  * - boot device = bit 15:0
@@ -55,10 +59,32 @@
 #define BOOTROM_INSTANCE_SHIFT	16
 
 /* BSEC OTP index */
+#define BSEC_OTP_RPN	1
 #define BSEC_OTP_SERIAL	13
+#define BSEC_OTP_PKG	16
 #define BSEC_OTP_MAC	57
 
+/* Device Part Number (RPN) = OTP_DATA1 lower 8 bits */
+#define RPN_SHIFT	0
+#define RPN_MASK	GENMASK(7, 0)
+
+/* Package = bit 27:29 of OTP16
+ * - 100: LBGA448 (FFI) => AA = LFBGA 18x18mm 448 balls p. 0.8mm
+ * - 011: LBGA354 (LCI) => AB = LFBGA 16x16mm 359 balls p. 0.8mm
+ * - 010: TFBGA361 (FFC) => AC = TFBGA 12x12mm 361 balls p. 0.5mm
+ * - 001: TFBGA257 (LCC) => AD = TFBGA 10x10mm 257 balls p. 0.5mm
+ * - others: Reserved
+ */
+#define PKG_SHIFT	27
+#define PKG_MASK	GENMASK(2, 0)
+
+#define PKG_AA_LBGA448	4
+#define PKG_AB_LBGA354	3
+#define PKG_AC_TFBGA361	2
+#define PKG_AD_TFBGA257	1
+
 #if !defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD)
+#ifndef CONFIG_STM32MP1_TRUSTED
 static void security_init(void)
 {
 	/* Disable the backup domain write protection */
@@ -113,7 +139,12 @@
 	 * Bit 16 ITAMP1E: RTC power domain supply monitoring
 	 */
 	writel(0x0, TAMP_CR1);
+
+	/* GPIOZ: deactivate the security */
+	writel(BIT(0), RCC_MP_AHB5ENSETR);
+	writel(0x0, GPIOZ_SECCFGR);
 }
+#endif /* CONFIG_STM32MP1_TRUSTED */
 
 /*
  * Debug init
@@ -127,13 +158,19 @@
 }
 #endif /* !defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD) */
 
-static u32 get_bootmode(void)
+#if !defined(CONFIG_STM32MP1_TRUSTED) && \
+	(!defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD))
+/* get bootmode from ROM code boot context: saved in TAMP register */
+static void update_bootmode(void)
 {
 	u32 boot_mode;
-#if !defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD)
 	u32 bootrom_itf = readl(BOOTROM_PARAM_ADDR);
 	u32 bootrom_device, bootrom_instance;
 
+	/* enable TAMP clock = RTCAPBEN */
+	writel(BIT(8), RCC_MP_APB5ENSETR);
+
+	/* read bootrom context */
 	bootrom_device =
 		(bootrom_itf & BOOTROM_MODE_MASK) >> BOOTROM_MODE_SHIFT;
 	bootrom_instance =
@@ -147,12 +184,14 @@
 	clrsetbits_le32(TAMP_BOOT_CONTEXT,
 			TAMP_BOOT_MODE_MASK,
 			boot_mode << TAMP_BOOT_MODE_SHIFT);
-#else
-	/* read TAMP backup register */
-	boot_mode = (readl(TAMP_BOOT_CONTEXT) & TAMP_BOOT_MODE_MASK) >>
-		    TAMP_BOOT_MODE_SHIFT;
+}
 #endif
-	return boot_mode;
+
+u32 get_bootmode(void)
+{
+	/* read bootmode from TAMP backup register */
+	return (readl(TAMP_BOOT_CONTEXT) & TAMP_BOOT_MODE_MASK) >>
+		    TAMP_BOOT_MODE_SHIFT;
 }
 
 /*
@@ -167,16 +206,18 @@
 
 #if !defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD)
 	dbgmcu_init();
-
+#ifndef CONFIG_STM32MP1_TRUSTED
 	security_init();
+	update_bootmode();
+#endif
 #endif
 
-	/* get bootmode from BootRom context: saved in TAMP register */
 	boot_mode = get_bootmode();
 
 	if ((boot_mode & TAMP_BOOT_DEVICE_MASK) == BOOT_SERIAL_UART)
 		gd->flags |= GD_FLG_SILENT | GD_FLG_DISABLE_CONSOLE;
 #if defined(CONFIG_DEBUG_UART) && \
+	!defined(CONFIG_STM32MP1_TRUSTED) && \
 	(!defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD))
 	else
 		debug_uart_init();
@@ -203,25 +244,94 @@
 	return (read_idc() & DBGMCU_IDC_REV_ID_MASK) >> DBGMCU_IDC_REV_ID_SHIFT;
 }
 
+static u32 get_otp(int index, int shift, int mask)
+{
+	int ret;
+	struct udevice *dev;
+	u32 otp = 0;
+
+	ret = uclass_get_device_by_driver(UCLASS_MISC,
+					  DM_GET_DRIVER(stm32mp_bsec),
+					  &dev);
+
+	if (!ret)
+		ret = misc_read(dev, STM32_BSEC_SHADOW(index),
+				&otp, sizeof(otp));
+
+	return (otp >> shift) & mask;
+}
+
+/* Get Device Part Number (RPN) from OTP */
+static u32 get_cpu_rpn(void)
+{
+	return get_otp(BSEC_OTP_RPN, RPN_SHIFT, RPN_MASK);
+}
+
 u32 get_cpu_type(void)
 {
-	return (read_idc() & DBGMCU_IDC_DEV_ID_MASK) >> DBGMCU_IDC_DEV_ID_SHIFT;
+	u32 id;
+
+	id = (read_idc() & DBGMCU_IDC_DEV_ID_MASK) >> DBGMCU_IDC_DEV_ID_SHIFT;
+
+	return (id << 16) | get_cpu_rpn();
 }
 
+/* Get Package options from OTP */
+static u32 get_cpu_package(void)
+{
+	return get_otp(BSEC_OTP_PKG, PKG_SHIFT, PKG_MASK);
+}
+
 #if defined(CONFIG_DISPLAY_CPUINFO)
 int print_cpuinfo(void)
 {
-	char *cpu_s, *cpu_r;
+	char *cpu_s, *cpu_r, *pkg;
 
+	/* MPUs Part Numbers */
 	switch (get_cpu_type()) {
-	case CPU_STMP32MP15x:
-		cpu_s = "15x";
+	case CPU_STM32MP157Cxx:
+		cpu_s = "157C";
+		break;
+	case CPU_STM32MP157Axx:
+		cpu_s = "157A";
+		break;
+	case CPU_STM32MP153Cxx:
+		cpu_s = "153C";
+		break;
+	case CPU_STM32MP153Axx:
+		cpu_s = "153A";
+		break;
+	case CPU_STM32MP151Cxx:
+		cpu_s = "151C";
+		break;
+	case CPU_STM32MP151Axx:
+		cpu_s = "151A";
+		break;
+	default:
+		cpu_s = "????";
+		break;
+	}
+
+	/* Package */
+	switch (get_cpu_package()) {
+	case PKG_AA_LBGA448:
+		pkg = "AA";
+		break;
+	case PKG_AB_LBGA354:
+		pkg = "AB";
+		break;
+	case PKG_AC_TFBGA361:
+		pkg = "AC";
+		break;
+	case PKG_AD_TFBGA257:
+		pkg = "AD";
 		break;
 	default:
-		cpu_s = "?";
+		pkg = "??";
 		break;
 	}
 
+	/* REVISION */
 	switch (get_cpu_rev()) {
 	case CPU_REVA:
 		cpu_r = "A";
@@ -234,7 +344,7 @@
 		break;
 	}
 
-	printf("CPU: STM32MP%s.%s\n", cpu_s, cpu_r);
+	printf("CPU: STM32MP%s%s Rev.%s\n", cpu_s, pkg, cpu_r);
 
 	return 0;
 }
@@ -242,20 +352,48 @@
 
 static void setup_boot_mode(void)
 {
+	const u32 serial_addr[] = {
+		STM32_USART1_BASE,
+		STM32_USART2_BASE,
+		STM32_USART3_BASE,
+		STM32_UART4_BASE,
+		STM32_UART5_BASE,
+		STM32_USART6_BASE,
+		STM32_UART7_BASE,
+		STM32_UART8_BASE
+	};
 	char cmd[60];
 	u32 boot_ctx = readl(TAMP_BOOT_CONTEXT);
 	u32 boot_mode =
 		(boot_ctx & TAMP_BOOT_MODE_MASK) >> TAMP_BOOT_MODE_SHIFT;
 	int instance = (boot_mode & TAMP_BOOT_INSTANCE_MASK) - 1;
-
-	pr_debug("%s: boot_ctx=0x%x => boot_mode=%x, instance=%d\n",
-		 __func__, boot_ctx, boot_mode, instance);
+	u32 forced_mode = (boot_ctx & TAMP_BOOT_FORCED_MASK);
+	struct udevice *dev;
+	int alias;
 
+	pr_debug("%s: boot_ctx=0x%x => boot_mode=%x, instance=%d forced=%x\n",
+		 __func__, boot_ctx, boot_mode, instance, forced_mode);
 	switch (boot_mode & TAMP_BOOT_DEVICE_MASK) {
 	case BOOT_SERIAL_UART:
-		sprintf(cmd, "%d", instance);
-		env_set("boot_device", "uart");
+		if (instance > ARRAY_SIZE(serial_addr))
+			break;
+		/* serial : search associated alias in devicetree */
+		sprintf(cmd, "serial@%x", serial_addr[instance]);
+		if (uclass_get_device_by_name(UCLASS_SERIAL, cmd, &dev))
+			break;
+		if (fdtdec_get_alias_seq(gd->fdt_blob, "serial",
+					 dev_of_offset(dev), &alias))
+			break;
+		sprintf(cmd, "%d", alias);
+		env_set("boot_device", "serial");
 		env_set("boot_instance", cmd);
+
+		/* restore console on uart when not used */
+		if (gd->cur_serial_dev != dev) {
+			gd->flags &= ~(GD_FLG_SILENT |
+				       GD_FLG_DISABLE_CONSOLE);
+			printf("serial boot with console enabled!\n");
+		}
 		break;
 	case BOOT_SERIAL_USB:
 		env_set("boot_device", "usb");
@@ -279,6 +417,36 @@
 		pr_debug("unexpected boot mode = %x\n", boot_mode);
 		break;
 	}
+
+	switch (forced_mode) {
+	case BOOT_FASTBOOT:
+		printf("Enter fastboot!\n");
+		env_set("preboot", "env set preboot; fastboot 0");
+		break;
+	case BOOT_STM32PROG:
+		env_set("boot_device", "usb");
+		env_set("boot_instance", "0");
+		break;
+	case BOOT_UMS_MMC0:
+	case BOOT_UMS_MMC1:
+	case BOOT_UMS_MMC2:
+		printf("Enter UMS!\n");
+		instance = forced_mode - BOOT_UMS_MMC0;
+		sprintf(cmd, "env set preboot; ums 0 mmc %d", instance);
+		env_set("preboot", cmd);
+		break;
+	case BOOT_RECOVERY:
+		env_set("preboot", "env set preboot; run altbootcmd");
+		break;
+	case BOOT_NORMAL:
+		break;
+	default:
+		pr_debug("unexpected forced boot mode = %x\n", forced_mode);
+		break;
+	}
+
+	/* clear TAMP for next reboot */
+	clrsetbits_le32(TAMP_BOOT_CONTEXT, TAMP_BOOT_FORCED_MASK, BOOT_NORMAL);
 }
 
 /*
@@ -304,7 +472,7 @@
 	if (ret)
 		return ret;
 
-	ret = misc_read(dev, BSEC_OTP_MAC * 4 + STM32_BSEC_OTP_OFFSET,
+	ret = misc_read(dev, STM32_BSEC_SHADOW(BSEC_OTP_MAC),
 			otp, sizeof(otp));
 	if (ret < 0)
 		return ret;
@@ -342,12 +510,12 @@
 	if (ret)
 		return ret;
 
-	ret = misc_read(dev, BSEC_OTP_SERIAL * 4 + STM32_BSEC_OTP_OFFSET,
+	ret = misc_read(dev, STM32_BSEC_SHADOW(BSEC_OTP_SERIAL),
 			otp, sizeof(otp));
 	if (ret < 0)
 		return ret;
 
-	sprintf(serial_string, "%08x%08x%08x", otp[0], otp[1], otp[2]);
+	sprintf(serial_string, "%08X%08X%08X", otp[0], otp[1], otp[2]);
 	env_set("serial#", serial_string);
 
 	return 0;
diff --git a/arch/arm/mach-stm32mp/include/mach/stm32.h b/arch/arm/mach-stm32mp/include/mach/stm32.h
index 5d0bdca..c526c88 100644
--- a/arch/arm/mach-stm32mp/include/mach/stm32.h
+++ b/arch/arm/mach-stm32mp/include/mach/stm32.h
@@ -13,13 +13,10 @@
 #define STM32_RCC_BASE			0x50000000
 #define STM32_PWR_BASE			0x50001000
 #define STM32_DBGMCU_BASE		0x50081000
-#define STM32_BSEC_BASE			0x5C005000
 #define STM32_TZC_BASE			0x5C006000
 #define STM32_ETZPC_BASE		0x5C007000
 #define STM32_TAMP_BASE			0x5C00A000
 
-#ifdef CONFIG_DEBUG_UART_BASE
-/* hardcoded value can be only used for DEBUG UART */
 #define STM32_USART1_BASE		0x5C000000
 #define STM32_USART2_BASE		0x4000E000
 #define STM32_USART3_BASE		0x4000F000
@@ -28,7 +25,6 @@
 #define STM32_USART6_BASE		0x44003000
 #define STM32_UART7_BASE		0x40018000
 #define STM32_UART8_BASE		0x40019000
-#endif
 
 #define STM32_SYSRAM_BASE		0x2FFC0000
 #define STM32_SYSRAM_SIZE		SZ_256K
@@ -40,8 +36,10 @@
 /* enumerated used to identify the SYSCON driver instance */
 enum {
 	STM32MP_SYSCON_UNKNOWN,
-	STM32MP_SYSCON_STGEN,
+	STM32MP_SYSCON_ETZPC,
 	STM32MP_SYSCON_PWR,
+	STM32MP_SYSCON_STGEN,
+	STM32MP_SYSCON_SYSCFG,
 };
 
 /*
@@ -95,10 +93,25 @@
 #define TAMP_BOOT_MODE_SHIFT		8
 #define TAMP_BOOT_DEVICE_MASK		GENMASK(7, 4)
 #define TAMP_BOOT_INSTANCE_MASK		GENMASK(3, 0)
+#define TAMP_BOOT_FORCED_MASK		GENMASK(7, 0)
+
+enum forced_boot_mode {
+	BOOT_NORMAL = 0x00,
+	BOOT_FASTBOOT = 0x01,
+	BOOT_RECOVERY = 0x02,
+	BOOT_STM32PROG = 0x03,
+	BOOT_UMS_MMC0 = 0x10,
+	BOOT_UMS_MMC1 = 0x11,
+	BOOT_UMS_MMC2 = 0x12,
+};
 
 /* offset used for BSEC driver: misc_read and misc_write */
 #define STM32_BSEC_SHADOW_OFFSET	0x0
+#define STM32_BSEC_SHADOW(id)		(STM32_BSEC_SHADOW_OFFSET + (id) * 4)
 #define STM32_BSEC_OTP_OFFSET		0x80000000
+#define STM32_BSEC_OTP(id)		(STM32_BSEC_OTP_OFFSET + (id) * 4)
+
+#define BSEC_OTP_BOARD	59
 
 #endif /* __ASSEMBLY__*/
 #endif /* _MACH_STM32_H_ */
diff --git a/arch/arm/mach-stm32mp/include/mach/stm32mp1_smc.h b/arch/arm/mach-stm32mp/include/mach/stm32mp1_smc.h
new file mode 100644
index 0000000..8130546
--- /dev/null
+++ b/arch/arm/mach-stm32mp/include/mach/stm32mp1_smc.h
@@ -0,0 +1,64 @@
+/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */
+/*
+ * Copyright (C) 2019, STMicroelectronics - All Rights Reserved
+ */
+
+#ifndef __STM32MP1_SMC_H__
+#define __STM32MP1_SMC_H__
+
+#include <linux/arm-smccc.h>
+
+/*
+ * SMC function IDs for STM32 Service queries
+ * STM32 SMC services use the space between 0x82000000 and 0x8200FFFF
+ * like this is defined in SMC calling Convention by ARM
+ * for SiP (silicon Partner)
+ * http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html
+ */
+#define STM32_SMC_VERSION		0x82000000
+
+/* Secure Service access from Non-secure */
+#define STM32_SMC_BSEC			0x82001003
+
+/* Service for BSEC */
+#define STM32_SMC_READ_SHADOW		0x01
+#define STM32_SMC_PROG_OTP		0x02
+#define STM32_SMC_WRITE_SHADOW		0x03
+#define STM32_SMC_READ_OTP		0x04
+#define STM32_SMC_READ_ALL		0x05
+#define STM32_SMC_WRITE_ALL		0x06
+
+/* SMC error codes */
+#define STM32_SMC_OK			0x0
+#define STM32_SMC_NOT_SUPPORTED		-1
+#define STM32_SMC_FAILED		-2
+#define STM32_SMC_INVALID_PARAMS	-3
+
+#define stm32_smc_exec(svc, op, data1, data2) \
+	stm32_smc(svc, op, data1, data2, NULL)
+
+#ifdef CONFIG_ARM_SMCCC
+static inline u32 stm32_smc(u32 svc, u8 op, u32 data1, u32 data2, u32 *result)
+{
+	struct arm_smccc_res res;
+
+	arm_smccc_smc(svc, op, data1, data2, 0, 0, 0, 0, &res);
+
+	if (res.a0) {
+		pr_err("%s: Failed to exec in secure mode (err = %ld)\n",
+		       __func__, res.a0);
+		return -EINVAL;
+	}
+	if (result)
+		*result = (u32)res.a1;
+
+	return 0;
+}
+#else
+static inline u32 stm32_smc(u32 svc, u8 op, u32 data1, u32 data2, u32 *result)
+{
+	return 0;
+}
+#endif
+
+#endif /* __STM32MP1_SMC_H__ */
diff --git a/arch/arm/mach-stm32mp/include/mach/sys_proto.h b/arch/arm/mach-stm32mp/include/mach/sys_proto.h
index 41d4b40..71a3ba7 100644
--- a/arch/arm/mach-stm32mp/include/mach/sys_proto.h
+++ b/arch/arm/mach-stm32mp/include/mach/sys_proto.h
@@ -3,9 +3,15 @@
  * Copyright (C) 2015-2017, STMicroelectronics - All Rights Reserved
  */
 
-#define CPU_STMP32MP15x	0x500
+/* ID = Device Version (bit31:16) + Device Part Number (RPN) (bit15:0)*/
+#define CPU_STM32MP157Cxx	0x05000000
+#define CPU_STM32MP157Axx	0x05000001
+#define CPU_STM32MP153Cxx	0x05000024
+#define CPU_STM32MP153Axx	0x05000025
+#define CPU_STM32MP151Cxx	0x0500002E
+#define CPU_STM32MP151Axx	0x0500002F
 
-/* return CPU_STMP32MPxx constants */
+/* return CPU_STMP32MP...Xxx constants */
 u32 get_cpu_type(void);
 
 #define CPU_REVA	0x1000
@@ -13,3 +19,5 @@
 
 /* return CPU_REV constants */
 u32 get_cpu_rev(void);
+/* return boot mode */
+u32 get_bootmode(void);
diff --git a/arch/arm/mach-stm32mp/psci.c b/arch/arm/mach-stm32mp/psci.c
index 6ed2482..c2dff38 100644
--- a/arch/arm/mach-stm32mp/psci.c
+++ b/arch/arm/mach-stm32mp/psci.c
@@ -103,7 +103,13 @@
 
 int __secure psci_migrate_info_type(u32 function_id)
 {
-	/* Trusted OS is either not present or does not require migration */
+	/*
+	 * in Power_State_Coordination_Interface_PDD_v1_1_DEN0022D.pdf
+	 * return 2 = Trusted OS is either not present or does not require
+	 * migration, system of this type does not require the caller
+	 * to use the MIGRATE function.
+	 * MIGRATE function calls return NOT_SUPPORTED.
+	 */
 	return 2;
 }
 
diff --git a/arch/arm/mach-stm32mp/spl.c b/arch/arm/mach-stm32mp/spl.c
index 790973e..a3b0d6f 100644
--- a/arch/arm/mach-stm32mp/spl.c
+++ b/arch/arm/mach-stm32mp/spl.c
@@ -7,13 +7,14 @@
 #include <dm.h>
 #include <spl.h>
 #include <asm/io.h>
+#include <asm/arch/sys_proto.h>
+#include <linux/libfdt.h>
 
 u32 spl_boot_device(void)
 {
 	u32 boot_mode;
 
-	boot_mode = (readl(TAMP_BOOT_CONTEXT) & TAMP_BOOT_MODE_MASK) >>
-		    TAMP_BOOT_MODE_SHIFT;
+	boot_mode = get_bootmode();
 
 	switch (boot_mode) {
 	case BOOT_FLASH_SD_1:
@@ -22,6 +23,21 @@
 	case BOOT_FLASH_SD_2:
 	case BOOT_FLASH_EMMC_2:
 		return BOOT_DEVICE_MMC2;
+	case BOOT_SERIAL_UART_1:
+	case BOOT_SERIAL_UART_2:
+	case BOOT_SERIAL_UART_3:
+	case BOOT_SERIAL_UART_4:
+	case BOOT_SERIAL_UART_5:
+	case BOOT_SERIAL_UART_6:
+	case BOOT_SERIAL_UART_7:
+	case BOOT_SERIAL_UART_8:
+		return BOOT_DEVICE_UART;
+	case BOOT_SERIAL_USB_OTG:
+		return BOOT_DEVICE_USB;
+	case BOOT_FLASH_NAND_FMC:
+		return BOOT_DEVICE_NAND;
+	case BOOT_FLASH_NOR_QSPI:
+		return BOOT_DEVICE_SPI;
 	}
 
 	return BOOT_DEVICE_MMC1;
@@ -44,6 +60,21 @@
 	}
 }
 
+#ifdef CONFIG_SPL_DISPLAY_PRINT
+void spl_display_print(void)
+{
+	DECLARE_GLOBAL_DATA_PTR;
+	const char *model;
+
+	/* same code than show_board_info() but not compiled for SPL
+	 * see CONFIG_DISPLAY_BOARDINFO & common/board_info.c
+	 */
+	model = fdt_getprop(gd->fdt_blob, 0, "model", NULL);
+	if (model)
+		printf("Model: %s\n", model);
+}
+#endif
+
 void board_init_f(ulong dummy)
 {
 	struct udevice *dev;
@@ -80,7 +111,7 @@
 
 	ret = uclass_get_device(UCLASS_RAM, 0, &dev);
 	if (ret) {
-		debug("DRAM init failed: %d\n", ret);
-		return;
+		printf("DRAM init failed: %d\n", ret);
+		hang();
 	}
 }
diff --git a/arch/arm/mach-stm32mp/syscon.c b/arch/arm/mach-stm32mp/syscon.c
index eb7f435..242f834 100644
--- a/arch/arm/mach-stm32mp/syscon.c
+++ b/arch/arm/mach-stm32mp/syscon.c
@@ -9,10 +9,11 @@
 #include <asm/arch/stm32.h>
 
 static const struct udevice_id stm32mp_syscon_ids[] = {
-	{ .compatible = "st,stm32-stgen",
-	  .data = STM32MP_SYSCON_STGEN },
-	{ .compatible = "st,stm32mp1-pwr",
-	  .data = STM32MP_SYSCON_PWR },
+	{ .compatible = "st,stm32mp1-etzpc", .data = STM32MP_SYSCON_ETZPC },
+	{ .compatible = "st,stm32mp1-pwr", .data = STM32MP_SYSCON_PWR },
+	{ .compatible = "st,stm32-stgen", .data = STM32MP_SYSCON_STGEN },
+	{ .compatible = "st,stm32mp157-syscfg",
+	  .data = STM32MP_SYSCON_SYSCFG },
 	{ }
 };
 
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
index 152deb0..8110f23 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -426,10 +426,11 @@
 
 config DRAM_ZQ
 	int "sunxi dram zq value"
-	default 123 if MACH_SUN4I || MACH_SUN5I || MACH_SUN6I || MACH_SUN8I
+	default 123 if MACH_SUN4I || MACH_SUN5I || MACH_SUN6I || \
+		       MACH_SUN8I_A23 || MACH_SUN8I_A33 || MACH_SUN8I_A83T
 	default 127 if MACH_SUN7I
 	default 14779 if MACH_SUN8I_V3S
-	default 3881979 if MACH_SUN8I_R40 || MACH_SUN50I_H6
+	default 3881979 if MACH_SUNXI_H3_H5 || MACH_SUN8I_R40 || MACH_SUN50I_H6
 	default 4145117 if MACH_SUN9I
 	default 3881915 if MACH_SUN50I
 	---help---
@@ -438,6 +439,7 @@
 config DRAM_ODT_EN
 	bool "sunxi dram odt enable"
 	default y if MACH_SUN8I_A23
+	default y if MACH_SUNXI_H3_H5
 	default y if MACH_SUN8I_R40
 	default y if MACH_SUN50I
 	default y if MACH_SUN50I_H6
diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c
index b74eaf2..c6dd7b8 100644
--- a/arch/arm/mach-sunxi/board.c
+++ b/arch/arm/mach-sunxi/board.c
@@ -240,10 +240,12 @@
 	boot_source = readb(SPL_ADDR + 0x28);
 	switch (boot_source) {
 	case SUNXI_BOOTED_FROM_MMC0:
+	case SUNXI_BOOTED_FROM_MMC0_HIGH:
 		return BOOT_DEVICE_MMC1;
 	case SUNXI_BOOTED_FROM_NAND:
 		return BOOT_DEVICE_NAND;
 	case SUNXI_BOOTED_FROM_MMC2:
+	case SUNXI_BOOTED_FROM_MMC2_HIGH:
 		return BOOT_DEVICE_MMC2;
 	case SUNXI_BOOTED_FROM_SPI:
 		return BOOT_DEVICE_SPI;
diff --git a/arch/arm/mach-sunxi/dram_sun8i_a33.c b/arch/arm/mach-sunxi/dram_sun8i_a33.c
index 1da2727..5da0192 100644
--- a/arch/arm/mach-sunxi/dram_sun8i_a33.c
+++ b/arch/arm/mach-sunxi/dram_sun8i_a33.c
@@ -152,7 +152,7 @@
 	reg_val &= ~(0xff << 8);
 	reg_val &= ~(0xff << 0);
 	reg_val |= (0x33 << 8);
-	reg_val |= (0x8 << 0);
+	reg_val |= (0x10 << 0);
 	writel(reg_val, &mctl_ctl->dramtmg8);
 	/* Set phy interface time */
 	reg_val = (0x2 << 24) | (t_rdata_en << 16) | (0x1 << 8)
diff --git a/arch/mips/dts/Makefile b/arch/mips/dts/Makefile
index 665d3cc..3522e6c 100644
--- a/arch/mips/dts/Makefile
+++ b/arch/mips/dts/Makefile
@@ -5,6 +5,7 @@
 	linkit-smart-7688.dtb
 dtb-$(CONFIG_TARGET_AP121) += ap121.dtb
 dtb-$(CONFIG_TARGET_AP143) += ap143.dtb
+dtb-$(CONFIG_TARGET_AP152) += ap152.dtb
 dtb-$(CONFIG_TARGET_BOSTON) += img,boston.dtb
 dtb-$(CONFIG_TARGET_MALTA) += mti,malta.dtb
 dtb-$(CONFIG_TARGET_PIC32MZDASK) += pic32mzda_sk.dtb
diff --git a/arch/mips/dts/ap121.dts b/arch/mips/dts/ap121.dts
index 4ca1c70..f30af50 100644
--- a/arch/mips/dts/ap121.dts
+++ b/arch/mips/dts/ap121.dts
@@ -34,7 +34,7 @@
 	spi-flash@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		memory-map = <0x9f000000 0x00800000>;
 		spi-max-frequency = <25000000>;
 		reg = <0>;
diff --git a/arch/mips/dts/ap143.dts b/arch/mips/dts/ap143.dts
index 6aedd87..93a0980 100644
--- a/arch/mips/dts/ap143.dts
+++ b/arch/mips/dts/ap143.dts
@@ -34,9 +34,14 @@
 	spi-flash@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		memory-map = <0x9f000000 0x00800000>;
 		spi-max-frequency = <25000000>;
 		reg = <0>;
 	};
 };
+
+&gmac1 {
+	status = "okay";
+	phy-mode = "rgmii";
+};
diff --git a/arch/mips/dts/ap152.dts b/arch/mips/dts/ap152.dts
new file mode 100644
index 0000000..1722290
--- /dev/null
+++ b/arch/mips/dts/ap152.dts
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Rosy Song <rosysong@rosinson.com>
+ */
+
+/dts-v1/;
+#include "qca956x.dtsi"
+
+/ {
+	model = "AP152 Reference Board";
+	compatible = "qca,ap152", "qca,qca956x";
+
+	aliases {
+		spi0 = &spi0;
+		serial0 = &uart0;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&gmac0 {
+	phy-mode = "sgmii";
+	status = "okay";
+};
+
+&xtal {
+	clock-frequency = <25000000>;
+};
+
+&uart0 {
+	clock-frequency = <25000000>;
+	status = "okay";
+};
+
+&spi0 {
+	spi-max-frequency = <25000000>;
+	status = "okay";
+	spi-flash@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "spi-flash";
+		memory-map = <0x9f000000 0x01000000>;
+		spi-max-frequency = <25000000>;
+		reg = <0>;
+	};
+};
diff --git a/arch/mips/dts/brcm,bcm6838.dtsi b/arch/mips/dts/brcm,bcm6838.dtsi
index b6f9559..c060802 100644
--- a/arch/mips/dts/brcm,bcm6838.dtsi
+++ b/arch/mips/dts/brcm,bcm6838.dtsi
@@ -98,5 +98,32 @@
 
 			status = "disabled";
 		};
+
+		gpio_lo: gpio-controller@14e00100 {
+			compatible = "brcm,bcm6345-gpio";
+			reg = <0x14e00100 0x4>, <0x14e0012c 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			status = "disabled";
+		};
+
+		gpio_mid0: gpio-controller@14e00104 {
+			compatible = "brcm,bcm6345-gpio";
+			reg = <0x14e00104 0x4>, <0x14e00130 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			status = "disabled";
+		};
+
+		gpio_mid1: gpio-controller@14e00108 {
+			compatible = "brcm,bcm6345-gpio";
+			reg = <0x14e00108 0x4>, <0x14e00134 0x4>;
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			status = "disabled";
+		};
 	};
 };
diff --git a/arch/mips/dts/brcm,bcm968380gerg.dts b/arch/mips/dts/brcm,bcm968380gerg.dts
index 513045e..98471e3 100644
--- a/arch/mips/dts/brcm,bcm968380gerg.dts
+++ b/arch/mips/dts/brcm,bcm968380gerg.dts
@@ -38,3 +38,15 @@
 		label = "bcm968380gerg:green:usb";
 	};
 };
+
+&gpio_lo {
+	status = "okay";
+};
+
+&gpio_mid0 {
+	status = "okay";
+};
+
+&gpio_mid1 {
+	status = "okay";
+};
diff --git a/arch/mips/dts/comtrend,ar-5315u.dts b/arch/mips/dts/comtrend,ar-5315u.dts
index eb60aaa..28443b3 100644
--- a/arch/mips/dts/comtrend,ar-5315u.dts
+++ b/arch/mips/dts/comtrend,ar-5315u.dts
@@ -110,7 +110,7 @@
 	status = "okay";
 
 	spi-flash@0 {
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		reg = <0>;
 		#address-cells = <1>;
 		#size-cells = <1>;
diff --git a/arch/mips/dts/comtrend,ar-5387un.dts b/arch/mips/dts/comtrend,ar-5387un.dts
index 03e3851..12ace64 100644
--- a/arch/mips/dts/comtrend,ar-5387un.dts
+++ b/arch/mips/dts/comtrend,ar-5387un.dts
@@ -94,7 +94,7 @@
 	status = "okay";
 
 	spi-flash@0 {
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		reg = <0>;
 		#address-cells = <1>;
 		#size-cells = <1>;
diff --git a/arch/mips/dts/gardena-smart-gateway-mt7688.dts b/arch/mips/dts/gardena-smart-gateway-mt7688.dts
index 75f6037..eedde89 100644
--- a/arch/mips/dts/gardena-smart-gateway-mt7688.dts
+++ b/arch/mips/dts/gardena-smart-gateway-mt7688.dts
@@ -10,7 +10,7 @@
 
 / {
 	compatible = "gardena,smart-gateway-mt7688", "ralink,mt7628a-soc";
-	model = "Gardena smart-Gateway-MT7688";
+	model = "GARDENA smart Gateway (MT7688)";
 
 	aliases {
 		serial0 = &uart0;
@@ -97,7 +97,7 @@
 	spi-flash@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "spi-flash", "jedec,spi-nor";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <40000000>;
 		reg = <0>;
 	};
diff --git a/arch/mips/dts/jr2_pcb110.dts b/arch/mips/dts/jr2_pcb110.dts
index ddc30ff..6562221 100644
--- a/arch/mips/dts/jr2_pcb110.dts
+++ b/arch/mips/dts/jr2_pcb110.dts
@@ -5,6 +5,7 @@
 
 /dts-v1/;
 #include "mscc,jr2.dtsi"
+#include <dt-bindings/mscc/jr2_data.h>
 
 / {
 	model = "Jaguar2 Cu8-Sfp16 PCB110 Reference Board";
@@ -43,7 +44,7 @@
 &spi0 {
 	status = "okay";
 	spi-flash@0 {
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <18000000>; /* input clock */
 		reg = <0>; /* CS0 */
 	};
@@ -72,3 +73,78 @@
 	sgpio-ports = <0x3f00ffff>;
 	gpio-ranges = <&sgpio2 0 0 96>;
 };
+
+&mdio1 {
+	status = "okay";
+
+	phy0: ethernet-phy@0 {
+		reg = <0>;
+	};
+	phy1: ethernet-phy@1 {
+		reg = <1>;
+	};
+	phy2: ethernet-phy@2 {
+		reg = <2>;
+	};
+	phy3: ethernet-phy@3 {
+		reg = <3>;
+	};
+	phy4: ethernet-phy@4 {
+		reg = <4>;
+	};
+	phy5: ethernet-phy@5 {
+		reg = <5>;
+	};
+	phy6: ethernet-phy@6 {
+		reg = <6>;
+	};
+	phy7: ethernet-phy@7 {
+		reg = <7>;
+	};
+};
+
+&switch {
+	ethernet-ports {
+
+		port0: port@0 {
+			reg = <0>;
+			phy-handle = <&phy0>;
+			phys = <&serdes_hsio 0 SERDES1G(1) PHY_MODE_SGMII>;
+		};
+		port1: port@1 {
+			reg = <1>;
+			phy-handle = <&phy1>;
+			phys = <&serdes_hsio 1 SERDES1G(2) PHY_MODE_SGMII>;
+		};
+		port2: port@2 {
+			reg = <2>;
+			phy-handle = <&phy2>;
+			phys = <&serdes_hsio 2 SERDES1G(3) PHY_MODE_SGMII>;
+		};
+		port3: port@3 {
+			reg = <3>;
+			phy-handle = <&phy3>;
+			phys = <&serdes_hsio 3 SERDES1G(4) PHY_MODE_SGMII>;
+		};
+		port4: port@4 {
+			reg = <4>;
+			phy-handle = <&phy4>;
+			phys = <&serdes_hsio 4 SERDES1G(5) PHY_MODE_SGMII>;
+		};
+		port5: port@5 {
+			reg = <5>;
+			phy-handle = <&phy5>;
+			phys = <&serdes_hsio 5 SERDES1G(6) PHY_MODE_SGMII>;
+		};
+		port6: port@6 {
+			reg = <6>;
+			phy-handle = <&phy6>;
+			phys = <&serdes_hsio 6 SERDES1G(7) PHY_MODE_SGMII>;
+		};
+		port7: port@7 {
+			reg = <7>;
+			phy-handle = <&phy7>;
+			phys = <&serdes_hsio 7 SERDES1G(8) PHY_MODE_SGMII>;
+		};
+	};
+};
diff --git a/arch/mips/dts/jr2_pcb111.dts b/arch/mips/dts/jr2_pcb111.dts
index 4d411b6..74305a8 100644
--- a/arch/mips/dts/jr2_pcb111.dts
+++ b/arch/mips/dts/jr2_pcb111.dts
@@ -5,6 +5,7 @@
 
 /dts-v1/;
 #include "mscc,jr2.dtsi"
+#include <dt-bindings/mscc/jr2_data.h>
 
 / {
 	model = "Jaguar2 Cu48 PCB111 Reference Board";
@@ -43,7 +44,7 @@
 &spi0 {
 	status = "okay";
 	spi-flash@0 {
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <18000000>; /* input clock */
 		reg = <0>; /* CS0 */
 	};
@@ -72,3 +73,402 @@
 	sgpio-ports = <0xff000000>;
 	gpio-ranges = <&sgpio2 0 0 96>;
 };
+
+&mdio1 {
+	status = "okay";
+
+	phy0: ethernet-phy@0 {
+		reg = <0>;
+	};
+	phy1: ethernet-phy@1 {
+		reg = <1>;
+	};
+	phy2: ethernet-phy@2 {
+		reg = <2>;
+	};
+	phy3: ethernet-phy@3 {
+		reg = <3>;
+	};
+	phy4: ethernet-phy@4 {
+		reg = <4>;
+	};
+	phy5: ethernet-phy@5 {
+		reg = <5>;
+	};
+	phy6: ethernet-phy@6 {
+		reg = <6>;
+	};
+	phy7: ethernet-phy@7 {
+		reg = <7>;
+	};
+	phy8: ethernet-phy@8 {
+		reg = <8>;
+	};
+	phy9: ethernet-phy@9 {
+		reg = <9>;
+	};
+	phy10: ethernet-phy@10 {
+		reg = <10>;
+	};
+	phy11: ethernet-phy@11 {
+		reg = <11>;
+	};
+	phy12: ethernet-phy@12 {
+		reg = <12>;
+	};
+	phy13: ethernet-phy@13 {
+		reg = <13>;
+	};
+	phy14: ethernet-phy@14 {
+		reg = <14>;
+	};
+	phy15: ethernet-phy@15 {
+		reg = <15>;
+	};
+	phy16: ethernet-phy@16 {
+		reg = <16>;
+	};
+	phy17: ethernet-phy@17 {
+		reg = <17>;
+	};
+	phy18: ethernet-phy@18 {
+		reg = <18>;
+	};
+	phy19: ethernet-phy@19 {
+		reg = <19>;
+	};
+	phy20: ethernet-phy@20 {
+		reg = <20>;
+	};
+	phy21: ethernet-phy@21 {
+		reg = <21>;
+	};
+	phy22: ethernet-phy@22 {
+		reg = <22>;
+	};
+	phy23: ethernet-phy@23 {
+		reg = <23>;
+	};
+};
+
+&mdio2 {
+	status = "okay";
+
+	phy24: ethernet-phy@24 {
+		reg = <0>;
+	};
+	phy25: ethernet-phy@25 {
+		reg = <1>;
+	};
+	phy26: ethernet-phy@26 {
+		reg = <2>;
+	};
+	phy27: ethernet-phy@27 {
+		reg = <3>;
+	};
+	phy28: ethernet-phy@28 {
+		reg = <4>;
+	};
+	phy29: ethernet-phy@29 {
+		reg = <5>;
+	};
+	phy30: ethernet-phy@30 {
+		reg = <6>;
+	};
+	phy31: ethernet-phy@31 {
+		reg = <7>;
+	};
+	phy32: ethernet-phy@32 {
+		reg = <8>;
+	};
+	phy33: ethernet-phy@33 {
+		reg = <9>;
+	};
+	phy34: ethernet-phy@34 {
+		reg = <10>;
+	};
+	phy35: ethernet-phy@35 {
+		reg = <11>;
+	};
+	phy36: ethernet-phy@36 {
+		reg = <12>;
+	};
+	phy37: ethernet-phy@37 {
+		reg = <13>;
+	};
+	phy38: ethernet-phy@38 {
+		reg = <14>;
+	};
+	phy39: ethernet-phy@39 {
+		reg = <15>;
+	};
+	phy40: ethernet-phy@40 {
+		reg = <16>;
+	};
+	phy41: ethernet-phy@41 {
+		reg = <17>;
+	};
+	phy42: ethernet-phy@42 {
+		reg = <18>;
+	};
+	phy43: ethernet-phy@43 {
+		reg = <19>;
+	};
+	phy44: ethernet-phy@44 {
+		reg = <20>;
+	};
+	phy45: ethernet-phy@45 {
+		reg = <21>;
+	};
+	phy46: ethernet-phy@46 {
+		reg = <22>;
+	};
+	phy47: ethernet-phy@47 {
+		reg = <23>;
+	};
+};
+
+&switch {
+	ethernet-ports {
+		port0: port@0 {
+			reg = <0>;
+			phy-handle = <&phy0>;
+			phys = <&serdes_hsio 0 SERDES6G(4) PHY_MODE_QSGMII>;
+		};
+		port1: port@1 {
+			reg = <1>;
+			phy-handle = <&phy1>;
+			phys = <&serdes_hsio 1 0xff PHY_MODE_QSGMII>;
+		};
+		port2: port@2 {
+			reg = <2>;
+			phy-handle = <&phy2>;
+			phys = <&serdes_hsio 2 0xff PHY_MODE_QSGMII>;
+		};
+		port3: port@3 {
+			reg = <3>;
+			phy-handle = <&phy3>;
+			phys = <&serdes_hsio 3 0xff PHY_MODE_QSGMII>;
+		};
+		port4: port@4 {
+			reg = <4>;
+			phy-handle = <&phy4>;
+			phys = <&serdes_hsio 4 SERDES6G(5) PHY_MODE_QSGMII>;
+		};
+		port5: port@5 {
+			reg = <5>;
+			phy-handle = <&phy5>;
+			phys = <&serdes_hsio 5 0xff PHY_MODE_QSGMII>;
+		};
+		port6: port@6 {
+			reg = <6>;
+			phy-handle = <&phy6>;
+			phys = <&serdes_hsio 6 0xff PHY_MODE_QSGMII>;
+		};
+		port7: port@7 {
+			reg = <7>;
+			phy-handle = <&phy7>;
+			phys = <&serdes_hsio 7 0xff PHY_MODE_QSGMII>;
+		};
+		port8: port@8 {
+			reg = <8>;
+			phy-handle = <&phy8>;
+			phys = <&serdes_hsio 8 SERDES6G(6) PHY_MODE_QSGMII>;
+		};
+		port9: port@9 {
+			reg = <9>;
+			phy-handle = <&phy9>;
+			phys = <&serdes_hsio 9 0xff PHY_MODE_QSGMII>;
+		};
+		port10: port@10 {
+			reg = <10>;
+			phy-handle = <&phy10>;
+			phys = <&serdes_hsio 10 0xff PHY_MODE_QSGMII>;
+		};
+		port11: port@11 {
+			reg = <11>;
+			phy-handle = <&phy11>;
+			phys = <&serdes_hsio 11 0xff PHY_MODE_QSGMII>;
+		};
+		port12: port@12 {
+			reg = <12>;
+			phy-handle = <&phy12>;
+			phys = <&serdes_hsio 12 SERDES6G(7) PHY_MODE_QSGMII>;
+		};
+		port13: port@13 {
+			reg = <13>;
+			phy-handle = <&phy13>;
+			phys = <&serdes_hsio 13 0xff PHY_MODE_QSGMII>;
+		};
+		port14: port@14 {
+			reg = <14>;
+			phy-handle = <&phy14>;
+			phys = <&serdes_hsio 14 0xff PHY_MODE_QSGMII>;
+		};
+		port15: port@15 {
+			reg = <15>;
+			phy-handle = <&phy15>;
+			phys = <&serdes_hsio 15 0xff PHY_MODE_QSGMII>;
+		};
+		port16: port@16 {
+			reg = <16>;
+			phy-handle = <&phy16>;
+			phys = <&serdes_hsio 16 SERDES6G(8) PHY_MODE_QSGMII>;
+		};
+		port17: port@17 {
+			reg = <17>;
+			phy-handle = <&phy17>;
+			phys = <&serdes_hsio 17 0xff PHY_MODE_QSGMII>;
+		};
+		port18: port@18 {
+			reg = <18>;
+			phy-handle = <&phy18>;
+			phys = <&serdes_hsio 18 0xff PHY_MODE_QSGMII>;
+		};
+		port19: port@19 {
+			reg = <19>;
+			phy-handle = <&phy19>;
+			phys = <&serdes_hsio 19 0xff PHY_MODE_QSGMII>;
+		};
+		port20: port@20 {
+			reg = <20>;
+			phy-handle = <&phy20>;
+			phys = <&serdes_hsio 20 SERDES6G(9) PHY_MODE_QSGMII>;
+		};
+		port21: port@21 {
+			reg = <21>;
+			phy-handle = <&phy21>;
+			phys = <&serdes_hsio 21 0xff PHY_MODE_QSGMII>;
+		};
+		port22: port@22 {
+			reg = <22>;
+			phy-handle = <&phy22>;
+			phys = <&serdes_hsio 22 0xff PHY_MODE_QSGMII>;
+		};
+		port23: port@23 {
+			reg = <23>;
+			phy-handle = <&phy23>;
+			phys = <&serdes_hsio 23 0xff PHY_MODE_QSGMII>;
+		};
+		port24: port@24 {
+			reg = <24>;
+			phy-handle = <&phy24>;
+			phys = <&serdes_hsio 24 SERDES6G(10) PHY_MODE_QSGMII>;
+		};
+		port25: port@25 {
+			reg = <25>;
+			phy-handle = <&phy25>;
+			phys = <&serdes_hsio 25 0xff PHY_MODE_QSGMII>;
+		};
+		port26: port@26 {
+			reg = <26>;
+			phy-handle = <&phy26>;
+			phys = <&serdes_hsio 26 0xff PHY_MODE_QSGMII>;
+		};
+		port27: port@27 {
+			reg = <27>;
+			phy-handle = <&phy27>;
+			phys = <&serdes_hsio 27 0xff PHY_MODE_QSGMII>;
+		};
+		port28: port@28 {
+			reg = <28>;
+			phy-handle = <&phy28>;
+			phys = <&serdes_hsio 28 SERDES6G(11) PHY_MODE_QSGMII>;
+		};
+		port29: port@29 {
+			reg = <29>;
+			phy-handle = <&phy29>;
+			phys = <&serdes_hsio 29 0xff PHY_MODE_QSGMII>;
+		};
+		port30: port@30 {
+			reg = <30>;
+			phy-handle = <&phy30>;
+			phys = <&serdes_hsio 30 0xff PHY_MODE_QSGMII>;
+		};
+		port31: port@31 {
+			reg = <31>;
+			phy-handle = <&phy31>;
+			phys = <&serdes_hsio 31 0xff PHY_MODE_QSGMII>;
+		};
+		port32: port@32 {
+			reg = <32>;
+			phy-handle = <&phy32>;
+			phys = <&serdes_hsio 32 SERDES6G(12) PHY_MODE_QSGMII>;
+		};
+		port33: port@33 {
+			reg = <33>;
+			phy-handle = <&phy33>;
+			phys = <&serdes_hsio 33 0xff PHY_MODE_QSGMII>;
+		};
+		port34: port@34 {
+			reg = <34>;
+			phy-handle = <&phy34>;
+			phys = <&serdes_hsio 34 0xff PHY_MODE_QSGMII>;
+		};
+		port35: port@35 {
+			reg = <35>;
+			phy-handle = <&phy35>;
+			phys = <&serdes_hsio 35 0xff PHY_MODE_QSGMII>;
+		};
+		port36: port@36 {
+			reg = <36>;
+			phy-handle = <&phy36>;
+			phys = <&serdes_hsio 36 SERDES6G(13) PHY_MODE_QSGMII>;
+		};
+		port37: port@37 {
+			reg = <37>;
+			phy-handle = <&phy37>;
+			phys = <&serdes_hsio 37 0xff PHY_MODE_QSGMII>;
+		};
+		port38: port@38 {
+			reg = <38>;
+			phy-handle = <&phy38>;
+			phys = <&serdes_hsio 38 0xff PHY_MODE_QSGMII>;
+		};
+		port39: port@39 {
+			reg = <39>;
+			phy-handle = <&phy39>;
+			phys = <&serdes_hsio 39 0xff PHY_MODE_QSGMII>;
+		};
+		port40: port@40 {
+			reg = <40>;
+			phy-handle = <&phy40>;
+			phys = <&serdes_hsio 40 SERDES6G(14) PHY_MODE_QSGMII>;
+		};
+		port41: port@41 {
+			reg = <41>;
+			phy-handle = <&phy41>;
+			phys = <&serdes_hsio 41 0xff PHY_MODE_QSGMII>;
+		};
+		port42: port@42 {
+			reg = <42>;
+			phy-handle = <&phy42>;
+			phys = <&serdes_hsio 42 0xff PHY_MODE_QSGMII>;
+		};
+		port43: port@43 {
+			reg = <43>;
+			phy-handle = <&phy43>;
+			phys = <&serdes_hsio 43 0xff PHY_MODE_QSGMII>;
+		};
+		port44: port@44 {
+			reg = <44>;
+			phy-handle = <&phy44>;
+			phys = <&serdes_hsio 44 SERDES6G(15) PHY_MODE_QSGMII>;
+		};
+		port45: port@45 {
+			reg = <45>;
+			phy-handle = <&phy45>;
+			phys = <&serdes_hsio 45 0xff PHY_MODE_QSGMII>;
+		};
+		port46: port@46 {
+			reg = <46>;
+			phy-handle = <&phy46>;
+			phys = <&serdes_hsio 46 0xff PHY_MODE_QSGMII>;
+		};
+		port47: port@47 {
+			reg = <47>;
+			phy-handle = <&phy47>;
+			phys = <&serdes_hsio 47 0xff PHY_MODE_QSGMII>;
+		};
+	};
+};
diff --git a/arch/mips/dts/linkit-smart-7688.dts b/arch/mips/dts/linkit-smart-7688.dts
index c9db136..bb10402 100644
--- a/arch/mips/dts/linkit-smart-7688.dts
+++ b/arch/mips/dts/linkit-smart-7688.dts
@@ -38,7 +38,7 @@
 	spi-flash@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "spi-flash", "jedec,spi-nor";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <25000000>;
 		reg = <0>;
 	};
diff --git a/arch/mips/dts/luton_pcb090.dts b/arch/mips/dts/luton_pcb090.dts
index 315172b..fe457ba 100644
--- a/arch/mips/dts/luton_pcb090.dts
+++ b/arch/mips/dts/luton_pcb090.dts
@@ -48,7 +48,7 @@
 &spi0 {
 	status = "okay";
 	spi-flash@0 {
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <18000000>; /* input clock */
 		reg = <0>; /* CS0 */
 		spi-cs-high;
diff --git a/arch/mips/dts/luton_pcb091.dts b/arch/mips/dts/luton_pcb091.dts
index 9b4d628..f684cc8 100644
--- a/arch/mips/dts/luton_pcb091.dts
+++ b/arch/mips/dts/luton_pcb091.dts
@@ -54,7 +54,7 @@
 &spi0 {
 	status = "okay";
 	spi-flash@0 {
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <18000000>; /* input clock */
 		reg = <0>; /* CS0 */
 		spi-cs-high;
diff --git a/arch/mips/dts/mscc,jr2.dtsi b/arch/mips/dts/mscc,jr2.dtsi
index 0900926..7f5a96f 100644
--- a/arch/mips/dts/mscc,jr2.dtsi
+++ b/arch/mips/dts/mscc,jr2.dtsi
@@ -183,5 +183,121 @@
 			gpio-bank-name = "sgpio2_";
 			sgpio-clock = <0x14>;
 		};
+
+		switch: switch@1010000 {
+			compatible = "mscc,vsc7454-switch";
+			reg = <0x01040000 0x0100>,   // VTSS_TO_DEV_0
+			      <0x01050000 0x0100>,   // VTSS_TO_DEV_1
+			      <0x01060000 0x0100>,   // VTSS_TO_DEV_2
+			      <0x01070000 0x0100>,   // VTSS_TO_DEV_3
+			      <0x01080000 0x0100>,   // VTSS_TO_DEV_4
+			      <0x01090000 0x0100>,   // VTSS_TO_DEV_5
+			      <0x010a0000 0x0100>,   // VTSS_TO_DEV_6
+			      <0x010b0000 0x0100>,   // VTSS_TO_DEV_7
+			      <0x010c0000 0x0100>,   // VTSS_TO_DEV_8
+			      <0x010d0000 0x0100>,   // VTSS_TO_DEV_9
+			      <0x010e0000 0x0100>,   // VTSS_TO_DEV_10
+			      <0x010f0000 0x0100>,   // VTSS_TO_DEV_11
+			      <0x01100000 0x0100>,   // VTSS_TO_DEV_12
+			      <0x01110000 0x0100>,   // VTSS_TO_DEV_13
+			      <0x01120000 0x0100>,   // VTSS_TO_DEV_14
+			      <0x01130000 0x0100>,   // VTSS_TO_DEV_15
+			      <0x01140000 0x0100>,   // VTSS_TO_DEV_16
+			      <0x01150000 0x0100>,   // VTSS_TO_DEV_17
+			      <0x01160000 0x0100>,   // VTSS_TO_DEV_18
+			      <0x01170000 0x0100>,   // VTSS_TO_DEV_19
+			      <0x01180000 0x0100>,   // VTSS_TO_DEV_20
+			      <0x01190000 0x0100>,   // VTSS_TO_DEV_21
+			      <0x011a0000 0x0100>,   // VTSS_TO_DEV_22
+			      <0x011b0000 0x0100>,   // VTSS_TO_DEV_23
+			      <0x011c0000 0x0100>,   // VTSS_TO_DEV_24
+			      <0x011d0000 0x0100>,   // VTSS_TO_DEV_25
+			      <0x011e0000 0x0100>,   // VTSS_TO_DEV_26
+			      <0x011f0000 0x0100>,   // VTSS_TO_DEV_27
+			      <0x01200000 0x0100>,   // VTSS_TO_DEV_28
+			      <0x01210000 0x0100>,   // VTSS_TO_DEV_29
+			      <0x01220000 0x0100>,   // VTSS_TO_DEV_30
+			      <0x01230000 0x0100>,   // VTSS_TO_DEV_31
+			      <0x01240000 0x0100>,   // VTSS_TO_DEV_32
+			      <0x01250000 0x0100>,   // VTSS_TO_DEV_33
+			      <0x01260000 0x0100>,   // VTSS_TO_DEV_34
+			      <0x01270000 0x0100>,   // VTSS_TO_DEV_35
+			      <0x01280000 0x0100>,   // VTSS_TO_DEV_36
+			      <0x01290000 0x0100>,   // VTSS_TO_DEV_37
+			      <0x012a0000 0x0100>,   // VTSS_TO_DEV_38
+			      <0x012b0000 0x0100>,   // VTSS_TO_DEV_39
+			      <0x012c0000 0x0100>,   // VTSS_TO_DEV_40
+			      <0x012d0000 0x0100>,   // VTSS_TO_DEV_41
+			      <0x012e0000 0x0100>,   // VTSS_TO_DEV_42
+			      <0x012f0000 0x0100>,   // VTSS_TO_DEV_43
+			      <0x01300000 0x0100>,   // VTSS_TO_DEV_44
+			      <0x01310000 0x0100>,   // VTSS_TO_DEV_45
+			      <0x01320000 0x0100>,   // VTSS_TO_DEV_46
+			      <0x01330000 0x0100>,   // VTSS_TO_DEV_47
+			      <0x01f00000 0x100000>, // ANA_AC
+			      <0x01d00000 0x100000>, // ANA_CL
+			      <0x01e00000 0x100000>, // ANA_L2
+			      <0x01410000 0x10000>,  // ASM
+			      <0x01460000 0x10000>,  // HSIO
+			      <0x01420000 0x00000>,  // LRN
+			      <0x017d0000 0x10000>,  // QFWD
+			      <0x01020000 0x20000>,  // QS
+			      <0x017e0000 0x10000>,  // QSYS
+			      <0x01b00000 0x80000>;  // REW
+			reg-names = "port0", "port1", "port2", "port3", "port4",
+				    "port5", "port6", "port7", "port8", "port9",
+				    "port10", "port11", "port12", "port13",
+				    "port14", "port15", "port16", "port17",
+				    "port18", "port19", "port20", "port21",
+				    "port22", "port23", "port24", "port25",
+				    "port26", "port27", "port28", "port29",
+				    "port30", "port31", "port32", "port33",
+				    "port34", "port35", "port36", "port37",
+				    "port38", "port39", "port40", "port41",
+				    "port42", "port43", "port44", "port45",
+				    "port46", "port47", "ana_ac", "ana_cl",
+				    "ana_l2", "asm", "hsio", "lrn", "qfwd",
+				    "qs", "qsys", "rew";
+			status = "okay";
+
+			ethernet-ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+			};
+		};
+
+		mdio0: mdio@010100c8 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "mscc,jr2-miim";
+			reg = <0x010100c8 0x24>;
+			status = "disabled";
+		};
+
+		mdio1: mdio@010100ec {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "mscc,jr2-miim";
+			reg = <0x010100ec 0x24>;
+			status = "disabled";
+		};
+
+		mdio2: mdio@01010110 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "mscc,jr2-miim";
+			reg = <0x01010110 0x24>;
+			status = "disabled";
+		};
+
+		hsio: syscon@10d0000 {
+			compatible = "mscc,jr2-hsio", "syscon", "simple-mfd";
+			reg = <0x10d0000 0x10000>;
+
+			serdes_hsio: serdes_hsio {
+				compatible = "mscc,vsc7454-serdes";
+				#phy-cells = <3>;
+			};
+		};
 	};
 };
diff --git a/arch/mips/dts/mscc,ocelot_pcb.dtsi b/arch/mips/dts/mscc,ocelot_pcb.dtsi
index 90725d3..885b564 100644
--- a/arch/mips/dts/mscc,ocelot_pcb.dtsi
+++ b/arch/mips/dts/mscc,ocelot_pcb.dtsi
@@ -29,7 +29,7 @@
 	pinctrl-names = "default";
 
 	spi-flash@0 {
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <18000000>; /* input clock */
 		reg = <0>; /* CS0 */
 	};
diff --git a/arch/mips/dts/mscc,servalt.dtsi b/arch/mips/dts/mscc,servalt.dtsi
index 4beb7a3..45ae2de 100644
--- a/arch/mips/dts/mscc,servalt.dtsi
+++ b/arch/mips/dts/mscc,servalt.dtsi
@@ -145,5 +145,45 @@
 			#gpio-cells = <2>;
 			gpio-ranges = <&sgpio 0 0 128>;
 		};
+
+		switch: switch@1010000 {
+			compatible = "mscc,vsc7437-switch";
+			reg = <0x01030000 0x0100>,   // VTSS_TO_DEV_0
+			      <0x01040000 0x0100>,   // VTSS_TO_DEV_1
+			      <0x01f00000 0x100000>, // ANA_AC
+			      <0x01d00000 0x100000>, // ANA_CL
+			      <0x01e00000 0x100000>, // ANA_L2
+			      <0x01120000 0x10000>,  // ASM
+			      <0x01130000 0x00000>,  // LRN
+			      <0x017d0000 0x10000>,  // QFWD
+			      <0x01020000 0x20000>,  // QS
+			      <0x017e0000 0x10000>,  // QSYS
+			      <0x01b00000 0x80000>;  // REW
+			reg-names = "port0", "port1",
+				    "ana_ac", "ana_cl", "ana_l2", "asm", "lrn",
+				    "qfwd", "qs", "qsys", "rew";
+			status = "okay";
+
+			ethernet-ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+			};
+		};
+
+		mdio0: mdio@010100c4 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "mscc,jr2-miim";
+			reg = <0x010100c4 0x24>;
+			status = "disabled";
+		};
+
+		mdio1: mdio@010100e8 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "mscc,jr2-miim";
+			reg = <0x010100e8 0x24>;
+			status = "disabled";
+		};
 	};
 };
diff --git a/arch/mips/dts/netgear,cg3100d.dts b/arch/mips/dts/netgear,cg3100d.dts
index a3d4cd5..a42a0da 100644
--- a/arch/mips/dts/netgear,cg3100d.dts
+++ b/arch/mips/dts/netgear,cg3100d.dts
@@ -93,7 +93,7 @@
 	status = "okay";
 
 	spi-flash@0 {
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		reg = <0>;
 		#address-cells = <1>;
 		#size-cells = <1>;
diff --git a/arch/mips/dts/qca953x.dtsi b/arch/mips/dts/qca953x.dtsi
index ba29ea2..90d34dd 100644
--- a/arch/mips/dts/qca953x.dtsi
+++ b/arch/mips/dts/qca953x.dtsi
@@ -65,6 +65,37 @@
 
 				status = "disabled";
 			};
+
+			gmac0: eth0@0x19000000 {
+				compatible = "qca,ag953x-mac";
+				reg = <0x19000000 0x200>;
+				phy = <&phy4>;
+				phy-mode = "rmii";
+
+				status = "disabled";
+			};
+
+			gmac1: eth1@0x1a000000 {
+				compatible = "qca,ag953x-mac";
+				reg = <0x1a000000 0x200>;
+				phy = <&phy0>;
+				phy-mode = "rgmii";
+
+				status = "disabled";
+
+				mdio {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					phy0: ethernet-phy@0 {
+						reg = <0>;
+						phy-mode = "rmii";
+					};
+					phy4: ethernet-phy@4 {
+						reg = <4>;
+						phy-mode = "rmii";
+					};
+				};
+			};
 		};
 
 		spi0: spi@1f000000 {
diff --git a/arch/mips/dts/qca956x.dtsi b/arch/mips/dts/qca956x.dtsi
new file mode 100644
index 0000000..6cb360b
--- /dev/null
+++ b/arch/mips/dts/qca956x.dtsi
@@ -0,0 +1,87 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Rosy Song <rosysong@rosinson.com>
+ */
+
+#include "skeleton.dtsi"
+
+/ {
+	compatible = "qca,qca956x";
+
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "mips,mips74Kc";
+			reg = <0>;
+		};
+	};
+
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		xtal: xtal {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-output-names = "xtal";
+		};
+	};
+
+	ahb {
+		compatible = "simple-bus";
+		ranges;
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		apb {
+			compatible = "simple-bus";
+			ranges;
+
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			uart0: uart@18020000 {
+				compatible = "ns16550";
+				reg = <0x18020000 0x20>;
+				reg-shift = <2>;
+
+				status = "disabled";
+			};
+
+			gmac0: eth@0x19000000 {
+				compatible = "qca,ag956x-mac";
+				reg = <0x19000000 0x200>;
+				phy = <&phy0>;
+				phy-mode = "sgmii";
+
+				status = "disabled";
+
+				mdio {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					phy0: ethernet-phy@0 {
+						reg = <0>;
+					};
+				};
+			};
+		};
+
+		spi0: spi@1f000000 {
+			compatible = "qca,ar7100-spi";
+			reg = <0x1f000000 0x10>;
+
+			status = "disabled";
+
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+	};
+};
diff --git a/arch/mips/dts/sagem,f@st1704.dts b/arch/mips/dts/sagem,f@st1704.dts
index ec6846d..98ed353 100644
--- a/arch/mips/dts/sagem,f@st1704.dts
+++ b/arch/mips/dts/sagem,f@st1704.dts
@@ -59,7 +59,7 @@
 	status = "okay";
 
 	spi-flash@0 {
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		reg = <0>;
 		#address-cells = <1>;
 		#size-cells = <1>;
diff --git a/arch/mips/dts/serval2_pcb112.dts b/arch/mips/dts/serval2_pcb112.dts
index fe025f4..5777a77 100644
--- a/arch/mips/dts/serval2_pcb112.dts
+++ b/arch/mips/dts/serval2_pcb112.dts
@@ -5,6 +5,7 @@
 
 /dts-v1/;
 #include "mscc,jr2.dtsi"
+#include <dt-bindings/mscc/jr2_data.h>
 
 / {
 	model = "Serval2 NID PCB112 Reference Board";
@@ -43,7 +44,7 @@
 &spi0 {
 	status = "okay";
 	spi-flash@0 {
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <18000000>; /* input clock */
 		reg = <0>; /* CS0 */
 	};
@@ -58,3 +59,46 @@
 	status = "okay";
 	sgpio-ports = <0x3fe0ffff>;
 };
+
+&mdio0 {
+	status = "okay";
+
+	phy16: ethernet-phy@16 {
+		reg = <16>;
+	};
+	phy17: ethernet-phy@17 {
+		reg = <17>;
+	};
+	phy18: ethernet-phy@18 {
+		reg = <18>;
+	};
+	phy19: ethernet-phy@19 {
+		reg = <19>;
+	};
+};
+
+&switch {
+	ethernet-ports {
+
+		port0: port@0 {
+			reg = <24>;
+			phy-handle = <&phy16>;
+			phys = <&serdes_hsio 24 SERDES6G(0) PHY_MODE_SGMII>;
+		};
+		port1: port@1 {
+			reg = <25>;
+			phy-handle = <&phy17>;
+			phys = <&serdes_hsio 25 SERDES6G(1) PHY_MODE_SGMII>;
+		};
+		port2: port@2 {
+			reg = <26>;
+			phy-handle = <&phy18>;
+			phys = <&serdes_hsio 26 SERDES6G(2) PHY_MODE_SGMII>;
+		};
+		port3: port@3 {
+			reg = <27>;
+			phy-handle = <&phy19>;
+			phys = <&serdes_hsio 27 SERDES6G(3) PHY_MODE_SGMII>;
+		};
+	};
+};
diff --git a/arch/mips/dts/serval_pcb105.dts b/arch/mips/dts/serval_pcb105.dts
index d0d6fac..1598669 100644
--- a/arch/mips/dts/serval_pcb105.dts
+++ b/arch/mips/dts/serval_pcb105.dts
@@ -43,7 +43,7 @@
 &spi0 {
 	status = "okay";
 	spi-flash@0 {
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <18000000>; /* input clock */
 		reg = <0>; /* CS0 */
 		spi-cs-high;
diff --git a/arch/mips/dts/serval_pcb106.dts b/arch/mips/dts/serval_pcb106.dts
index 1198249..fb3524b 100644
--- a/arch/mips/dts/serval_pcb106.dts
+++ b/arch/mips/dts/serval_pcb106.dts
@@ -43,7 +43,7 @@
 &spi0 {
 	status = "okay";
 	spi-flash@0 {
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <18000000>; /* input clock */
 		reg = <0>; /* CS0 */
 		spi-cs-high;
diff --git a/arch/mips/dts/servalt_pcb116.dts b/arch/mips/dts/servalt_pcb116.dts
index fb33312..313b099 100644
--- a/arch/mips/dts/servalt_pcb116.dts
+++ b/arch/mips/dts/servalt_pcb116.dts
@@ -43,7 +43,7 @@
 &spi0 {
 	status = "okay";
 	spi-flash@0 {
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <18000000>; /* input clock */
 		reg = <0>; /* CS0 */
 		spi-cs-high;
@@ -54,3 +54,28 @@
 	status = "okay";
 	sgpio-ports = <0x0000fe7f>;
 };
+
+&mdio0 {
+	status = "okay";
+
+	phy0: ethernet-phy@0 {
+		reg = <0>;
+	};
+	phy1: ethernet-phy@1 {
+		reg = <1>;
+	};
+};
+
+&switch {
+	ethernet-ports {
+
+		port0: port@0 {
+			reg = <0>;
+			phy-handle = <&phy0>;
+		};
+		port1: port@1 {
+			reg = <1>;
+			phy-handle = <&phy1>;
+		};
+	};
+};
diff --git a/arch/mips/dts/tplink_wdr4300.dts b/arch/mips/dts/tplink_wdr4300.dts
index 96cf0da..2bcad6d 100644
--- a/arch/mips/dts/tplink_wdr4300.dts
+++ b/arch/mips/dts/tplink_wdr4300.dts
@@ -35,7 +35,7 @@
 	spi-flash@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "spi-flash";
+		compatible = "jedec,spi-nor";
 		memory-map = <0x1e000000 0x00800000>;
 		spi-max-frequency = <25000000>;
 		reg = <0>;
diff --git a/arch/mips/lib/bootm.c b/arch/mips/lib/bootm.c
index deca518..35152cb 100644
--- a/arch/mips/lib/bootm.c
+++ b/arch/mips/lib/bootm.c
@@ -215,23 +215,6 @@
 	}
 }
 
-static int boot_reloc_ramdisk(bootm_headers_t *images)
-{
-	ulong rd_len = images->rd_end - images->rd_start;
-
-	/*
-	 * In case of legacy uImage's, relocation of ramdisk is already done
-	 * by do_bootm_states() and should not repeated in 'bootm prep'.
-	 */
-	if (images->state & BOOTM_STATE_RAMDISK) {
-		debug("## Ramdisk already relocated\n");
-		return 0;
-	}
-
-	return boot_ramdisk_high(&images->lmb, images->rd_start,
-		rd_len, &images->initrd_start, &images->initrd_end);
-}
-
 static int boot_reloc_fdt(bootm_headers_t *images)
 {
 	/*
@@ -270,8 +253,6 @@
 
 static void boot_prep_linux(bootm_headers_t *images)
 {
-	boot_reloc_ramdisk(images);
-
 	if (CONFIG_IS_ENABLED(MIPS_BOOT_FDT) && images->ft_len) {
 		boot_reloc_fdt(images);
 		boot_setup_fdt(images);
diff --git a/arch/mips/mach-ath79/Kconfig b/arch/mips/mach-ath79/Kconfig
index bc86f59..bdb23b5 100644
--- a/arch/mips/mach-ath79/Kconfig
+++ b/arch/mips/mach-ath79/Kconfig
@@ -33,6 +33,15 @@
 	help
 	  This supports QCA/Atheros qca953x family SOCs.
 
+config SOC_QCA956X
+	bool
+	select MIPS_TUNE_74KC
+	select SUPPORTS_BIG_ENDIAN
+	select SUPPORTS_CPU_MIPS32_R1
+	select SUPPORTS_CPU_MIPS32_R2
+	help
+	  This supports QCA/Atheros qca956x family SOCs.
+
 choice
 	prompt "Board select"
 
@@ -44,6 +53,10 @@
 	bool "AP143 Reference Board"
 	select SOC_QCA953X
 
+config TARGET_AP152
+	bool "AP152 Reference Board"
+	select SOC_QCA956X
+
 config BOARD_TPLINK_WDR4300
 	bool "TP-Link WDR4300 Board"
 	select SOC_AR934X
@@ -52,6 +65,7 @@
 
 source "board/qca/ap121/Kconfig"
 source "board/qca/ap143/Kconfig"
+source "board/qca/ap152/Kconfig"
 source "board/tplink/wdr4300/Kconfig"
 
 endmenu
diff --git a/arch/mips/mach-ath79/Makefile b/arch/mips/mach-ath79/Makefile
index 7aa40c6..fbd40c0 100644
--- a/arch/mips/mach-ath79/Makefile
+++ b/arch/mips/mach-ath79/Makefile
@@ -7,3 +7,4 @@
 obj-$(CONFIG_SOC_AR933X)	+= ar933x/
 obj-$(CONFIG_SOC_AR934X)	+= ar934x/
 obj-$(CONFIG_SOC_QCA953X)	+= qca953x/
+obj-$(CONFIG_SOC_QCA956X)	+= qca956x/
diff --git a/arch/mips/mach-ath79/include/mach/ar71xx_regs.h b/arch/mips/mach-ath79/include/mach/ar71xx_regs.h
index 5d371bb..5888f6e 100644
--- a/arch/mips/mach-ath79/include/mach/ar71xx_regs.h
+++ b/arch/mips/mach-ath79/include/mach/ar71xx_regs.h
@@ -194,6 +194,9 @@
 #define QCA956X_WMAC_BASE \
 	(AR71XX_APB_BASE + 0x00100000)
 #define QCA956X_WMAC_SIZE				0x20000
+#define QCA956X_RTC_BASE \
+	(AR71XX_APB_BASE + 0x00107000)
+#define QCA956X_RTC_SIZE					0x1000
 #define QCA956X_EHCI0_BASE				0x1b000000
 #define QCA956X_EHCI1_BASE				0x1b400000
 #define QCA956X_EHCI_SIZE				0x200
@@ -201,6 +204,10 @@
 	(AR71XX_APB_BASE + 0x00070000)
 #define QCA956X_GMAC_SIZE				0x64
 
+#define QCA956X_SRIF_BASE \
+	(AR71XX_APB_BASE + 0x00116000)
+#define QCA956X_SRIF_SIZE				0x1000
+
 /*
  * DDR_CTRL block
  */
@@ -278,6 +285,18 @@
 #define QCA953X_DDR_REG_CTL_CONF			0x108
 #define QCA953X_DDR_REG_CONFIG3				0x15c
 
+#define QCA956X_DDR_REG_TAP_CTRL2			0x24
+#define QCA956X_DDR_REG_TAP_CTRL3			0x28
+#define QCA956X_DDR_REG_DDR2_CONFIG			0xb8
+#define QCA956X_DDR_REG_DDR2_EMR2			0xbc
+#define QCA956X_DDR_REG_DDR2_EMR3			0xc0
+#define QCA956X_DDR_REG_BURST				0xc4
+#define QCA956X_DDR_REG_BURST2				0xc8
+#define QCA956X_DDR_REG_TIMEOUT_MAX			0xcc
+#define QCA956X_DDR_REG_FSM_WAIT_CTRL			0xe4
+#define QCA956X_DDR_REG_CTL_CONF			0x108
+#define QCA956X_DDR_REG_DDR3_CONFIG			0x15c
+
 /*
  * PLL block
  */
@@ -519,6 +538,13 @@
 #define QCA956X_PLL_DDR_CONFIG_REG			0x08
 #define QCA956X_PLL_DDR_CONFIG1_REG			0x0c
 #define QCA956X_PLL_CLK_CTRL_REG			0x10
+#define QCA956X_PLL_SWITCH_CLK_CTRL_REG			0x28
+#define QCA956X_PLL_ETH_XMII_CTRL_REG			0x30
+#define QCA956X_PLL_DDR_DIT_FRAC_REG			0x38
+#define QCA956X_PLL_DDR_DIT2_FRAC_REG			0x3c
+#define QCA956X_PLL_CPU_DIT_FRAC_REG			0x40
+#define QCA956X_PLL_CPU_DIT2_FRAC_REG			0x44
+#define QCA956X_PLL_ETH_SGMII_SERDES_REG		0x4c
 
 #define QCA956X_PLL_CPU_CONFIG_REFDIV_SHIFT		12
 #define QCA956X_PLL_CPU_CONFIG_REFDIV_MASK		0x1f
@@ -528,7 +554,7 @@
 #define QCA956X_PLL_CPU_CONFIG1_NFRAC_L_SHIFT		0
 #define QCA956X_PLL_CPU_CONFIG1_NFRAC_L_MASK		0x1f
 #define QCA956X_PLL_CPU_CONFIG1_NFRAC_H_SHIFT		5
-#define QCA956X_PLL_CPU_CONFIG1_NFRAC_H_MASK		0x3fff
+#define QCA956X_PLL_CPU_CONFIG1_NFRAC_H_MASK		0x1fff
 #define QCA956X_PLL_CPU_CONFIG1_NINT_SHIFT		18
 #define QCA956X_PLL_CPU_CONFIG1_NINT_MASK		0x1ff
 
@@ -540,7 +566,7 @@
 #define QCA956X_PLL_DDR_CONFIG1_NFRAC_L_SHIFT		0
 #define QCA956X_PLL_DDR_CONFIG1_NFRAC_L_MASK		0x1f
 #define QCA956X_PLL_DDR_CONFIG1_NFRAC_H_SHIFT		5
-#define QCA956X_PLL_DDR_CONFIG1_NFRAC_H_MASK		0x3fff
+#define QCA956X_PLL_DDR_CONFIG1_NFRAC_H_MASK		0x1fff
 #define QCA956X_PLL_DDR_CONFIG1_NINT_SHIFT		18
 #define QCA956X_PLL_DDR_CONFIG1_NINT_MASK		0x1ff
 
@@ -756,6 +782,17 @@
 #define QCA955X_RESET_MBOX				BIT(1)
 #define QCA955X_RESET_I2S				BIT(0)
 
+#define QCA956X_RESET_EXTERNAL				BIT(28)
+#define QCA956X_RESET_FULL_CHIP				BIT(24)
+#define QCA956X_RESET_GE1_MDIO				BIT(23) /* Reserved in datasheet */
+#define QCA956X_RESET_GE0_MDIO				BIT(22)
+#define QCA956X_RESET_GE1_MAC				BIT(13) /* Reserved in datasheet */
+#define QCA956X_RESET_SGMII_ASSERT			BIT(12)
+#define QCA956X_RESET_GE0_MAC				BIT(9)
+#define QCA956X_RESET_SGMII				BIT(8)
+#define QCA956X_RESET_SGMII_ANALOG				BIT(2)
+#define QCA956X_RESET_SWITCH				BIT(0)
+
 #define AR933X_BOOTSTRAP_MDIO_GPIO_EN			BIT(18)
 #define AR933X_BOOTSTRAP_DDR2				BIT(13)
 #define AR933X_BOOTSTRAP_EEPBUSY			BIT(4)
@@ -1099,8 +1136,12 @@
 #define QCA953X_GPIO_IN_MUX_UART0_SIN			9
 #define QCA953X_GPIO_IN_MUX_SPI_DATA_IN			8
 
+#define QCA956X_GPIO(x)					BIT(x)
+#define QCA956X_GPIO_MUX_MASK(x)			(0xff << (x))
 #define QCA956X_GPIO_OUT_MUX_GE0_MDO			32
 #define QCA956X_GPIO_OUT_MUX_GE0_MDC			33
+#define QCA956X_GPIO_IN_MUX_UART0_SIN			0x12
+#define QCA956X_GPIO_OUT_MUX_UART0_SOUT			0x16
 
 #define AR71XX_GPIO_COUNT				16
 #define AR7240_GPIO_COUNT				18
@@ -1179,6 +1220,25 @@
 #define QCA953X_SRIF_DPLL2_OUTDIV_SHIFT			13
 #define QCA953X_SRIF_DPLL2_OUTDIV_MASK			0x7
 
+#define QCA956X_SRIF_BB_DPLL1_REG			0x180
+#define QCA956X_SRIF_BB_DPLL2_REG			0x184
+#define QCA956X_SRIF_BB_DPLL3_REG			0x188
+
+#define QCA956X_SRIF_CPU_DPLL1_REG			0xf00
+#define QCA956X_SRIF_CPU_DPLL2_REG			0xf04
+#define QCA956X_SRIF_CPU_DPLL3_REG			0xf08
+
+#define QCA956X_SRIF_DDR_DPLL1_REG			0xec0
+#define QCA956X_SRIF_DDR_DPLL2_REG			0xec4
+#define QCA956X_SRIF_DDR_DPLL3_REG			0xec8
+
+#define QCA956X_SRIF_PCIE_DPLL1_REG			0xc80
+#define QCA956X_SRIF_PCIE_DPLL2_REG			0xc84
+#define QCA956X_SRIF_PCIE_DPLL3_REG			0xc88
+
+#define QCA956X_SRIF_PMU1_REG				0xcc0
+#define QCA956X_SRIF_PMU2_REG				0xcc4
+
 /*
  * MII_CTRL block
  */
@@ -1261,4 +1321,17 @@
 #define QCA955X_ETH_CFG_RGMII_EN			BIT(0)
 #define QCA955X_ETH_CFG_GE0_SGMII			BIT(6)
 
+/*
+ * QCA956X GMAC Interface
+ */
+
+#define QCA956X_GMAC_REG_ETH_CFG			0x00
+#define QCA956X_GMAC_REG_SGMII_RESET			0x14
+#define QCA956X_GMAC_REG_SGMII_SERDES			0x18
+#define QCA956X_GMAC_REG_MR_AN_CTRL			0x1c
+#define QCA956X_GMAC_REG_SGMII_CONFIG			0x34
+#define QCA956X_GMAC_REG_SGMII_DEBUG			0x58
+
+#define QCA956X_ETH_CFG_GE0_SGMII			BIT(6)
+
 #endif /* __ASM_AR71XX_H */
diff --git a/arch/mips/mach-ath79/include/mach/ath79.h b/arch/mips/mach-ath79/include/mach/ath79.h
index 5de7a43..0fde507 100644
--- a/arch/mips/mach-ath79/include/mach/ath79.h
+++ b/arch/mips/mach-ath79/include/mach/ath79.h
@@ -2,6 +2,7 @@
 /*
  * Atheros AR71XX/AR724X/AR913X common definitions
  *
+ * Copyright (C) 2018-2019 Rosy Song <rosysong@rosinson.com>
  * Copyright (C) 2015-2016 Wills Wang <wills.wang@live.com>
  * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
  * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
@@ -146,4 +147,6 @@
 void ar934x_pll_init(const u16 cpu_mhz, const u16 ddr_mhz, const u16 ahb_mhz);
 void ar934x_ddr_init(const u16 cpu_mhz, const u16 ddr_mhz, const u16 ahb_mhz);
 
+void qca956x_pll_init(void);
+void qca956x_ddr_init(void);
 #endif /* __ASM_MACH_ATH79_H */
diff --git a/arch/mips/mach-ath79/qca956x/Makefile b/arch/mips/mach-ath79/qca956x/Makefile
new file mode 100644
index 0000000..3f5fc03
--- /dev/null
+++ b/arch/mips/mach-ath79/qca956x/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+obj-y += cpu.o
+obj-y += clk.o
+obj-y += ddr.o qca956x-ddr-tap.o
diff --git a/arch/mips/mach-ath79/qca956x/clk.c b/arch/mips/mach-ath79/qca956x/clk.c
new file mode 100644
index 0000000..33a44cf
--- /dev/null
+++ b/arch/mips/mach-ath79/qca956x/clk.c
@@ -0,0 +1,419 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Rosy Song <rosysong@rosinson.com>
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/addrspace.h>
+#include <asm/types.h>
+#include <mach/ar71xx_regs.h>
+#include <mach/ath79.h>
+#include <wait_bit.h>
+
+#define PLL_SRIF_DPLL2_KI_LSB 29
+#define PLL_SRIF_DPLL2_KI_MASK 0x60000000
+#define PLL_SRIF_DPLL2_KI_SET(x) \
+	(((x) << PLL_SRIF_DPLL2_KI_LSB) & PLL_SRIF_DPLL2_KI_MASK)
+#define PLL_SRIF_DPLL2_KD_LSB 25
+#define PLL_SRIF_DPLL2_KD_MASK 0x1e000000
+#define PLL_SRIF_DPLL2_KD_SET(x) \
+	(((x) << PLL_SRIF_DPLL2_KD_LSB) & PLL_SRIF_DPLL2_KD_MASK)
+#define PLL_SRIF_DPLL2_PLL_PWD_LSB 22
+#define PLL_SRIF_DPLL2_PLL_PWD_MASK 0x00400000
+#define PLL_SRIF_DPLL2_PLL_PWD_SET(x) \
+	(((x) << PLL_SRIF_DPLL2_PLL_PWD_LSB) & PLL_SRIF_DPLL2_PLL_PWD_MASK)
+#define PLL_SRIF_DPLL2_OUTDIV_LSB 19
+#define PLL_SRIF_DPLL2_OUTDIV_MASK 0x00380000
+#define PLL_SRIF_DPLL2_OUTDIV_SET(x) \
+	(((x) << PLL_SRIF_DPLL2_OUTDIV_LSB) & PLL_SRIF_DPLL2_OUTDIV_MASK)
+#define PLL_SRIF_DPLL2_PHASE_SHIFT_LSB 12
+#define PLL_SRIF_DPLL2_PHASE_SHIFT_MASK 0x0007f000
+#define PLL_SRIF_DPLL2_PHASE_SHIFT_SET(x) \
+	(((x) << PLL_SRIF_DPLL2_PHASE_SHIFT_LSB) & PLL_SRIF_DPLL2_PHASE_SHIFT_MASK)
+#define CPU_PLL_CONFIG_PLLPWD_LSB 30
+#define CPU_PLL_CONFIG_PLLPWD_MASK 0x40000000
+#define CPU_PLL_CONFIG_PLLPWD_SET(x) \
+	(((x) << CPU_PLL_CONFIG_PLLPWD_LSB) & CPU_PLL_CONFIG_PLLPWD_MASK)
+#define CPU_PLL_CONFIG_OUTDIV_LSB 19
+#define CPU_PLL_CONFIG_OUTDIV_MASK 0x00380000
+#define CPU_PLL_CONFIG_OUTDIV_SET(x) \
+	(((x) << CPU_PLL_CONFIG_OUTDIV_LSB) & CPU_PLL_CONFIG_OUTDIV_MASK)
+#define CPU_PLL_CONFIG_RANGE_LSB 17
+#define CPU_PLL_CONFIG_RANGE_MASK 0x00060000
+#define CPU_PLL_CONFIG_RANGE_SET(x) \
+	(((x) << CPU_PLL_CONFIG_RANGE_LSB) & CPU_PLL_CONFIG_RANGE_MASK)
+#define CPU_PLL_CONFIG_REFDIV_LSB 12
+#define CPU_PLL_CONFIG_REFDIV_MASK 0x0001f000
+#define CPU_PLL_CONFIG_REFDIV_SET(x) \
+	(((x) << CPU_PLL_CONFIG_REFDIV_LSB) & CPU_PLL_CONFIG_REFDIV_MASK)
+#define CPU_PLL_CONFIG1_NINT_LSB 18
+#define CPU_PLL_CONFIG1_NINT_MASK 0x07fc0000
+#define CPU_PLL_CONFIG1_NINT_SET(x) \
+	(((x) << CPU_PLL_CONFIG1_NINT_LSB) & CPU_PLL_CONFIG1_NINT_MASK)
+#define CPU_PLL_DITHER1_DITHER_EN_LSB 31
+#define CPU_PLL_DITHER1_DITHER_EN_MASK 0x80000000
+#define CPU_PLL_DITHER1_DITHER_EN_SET(x) \
+	(((x) << CPU_PLL_DITHER1_DITHER_EN_LSB) & CPU_PLL_DITHER1_DITHER_EN_MASK)
+#define CPU_PLL_DITHER1_UPDATE_COUNT_LSB 24
+#define CPU_PLL_DITHER1_UPDATE_COUNT_MASK 0x3f000000
+#define CPU_PLL_DITHER1_UPDATE_COUNT_SET(x) \
+	(((x) << CPU_PLL_DITHER1_UPDATE_COUNT_LSB) & CPU_PLL_DITHER1_UPDATE_COUNT_MASK)
+#define CPU_PLL_DITHER1_NFRAC_STEP_LSB 18
+#define CPU_PLL_DITHER1_NFRAC_STEP_MASK 0x00fc0000
+#define CPU_PLL_DITHER1_NFRAC_STEP_SET(x) \
+	(((x) << CPU_PLL_DITHER1_NFRAC_STEP_LSB) & CPU_PLL_DITHER1_NFRAC_STEP_MASK)
+#define CPU_PLL_DITHER1_NFRAC_MIN_LSB 0
+#define CPU_PLL_DITHER1_NFRAC_MIN_MASK 0x0003ffff
+#define CPU_PLL_DITHER1_NFRAC_MIN_SET(x) \
+	(((x) << CPU_PLL_DITHER1_NFRAC_MIN_LSB) & CPU_PLL_DITHER1_NFRAC_MIN_MASK)
+#define CPU_PLL_DITHER2_NFRAC_MAX_LSB 0
+#define CPU_PLL_DITHER2_NFRAC_MAX_MASK 0x0003ffff
+#define CPU_PLL_DITHER2_NFRAC_MAX_SET(x) \
+	(((x) << CPU_PLL_DITHER2_NFRAC_MAX_LSB) & CPU_PLL_DITHER2_NFRAC_MAX_MASK)
+#define DDR_PLL_CONFIG_PLLPWD_LSB 30
+#define DDR_PLL_CONFIG_PLLPWD_MASK 0x40000000
+#define DDR_PLL_CONFIG_PLLPWD_SET(x) \
+	(((x) << DDR_PLL_CONFIG_PLLPWD_LSB) & DDR_PLL_CONFIG_PLLPWD_MASK)
+#define DDR_PLL_CONFIG_OUTDIV_LSB 23
+#define DDR_PLL_CONFIG_OUTDIV_MASK 0x03800000
+#define DDR_PLL_CONFIG_OUTDIV_SET(x) \
+	(((x) << DDR_PLL_CONFIG_OUTDIV_LSB) & DDR_PLL_CONFIG_OUTDIV_MASK)
+#define DDR_PLL_CONFIG_RANGE_LSB 21
+#define DDR_PLL_CONFIG_RANGE_MASK 0x00600000
+#define DDR_PLL_CONFIG_RANGE_SET(x) \
+	(((x) << DDR_PLL_CONFIG_RANGE_LSB) & DDR_PLL_CONFIG_RANGE_MASK)
+#define DDR_PLL_CONFIG_REFDIV_LSB 16
+#define DDR_PLL_CONFIG_REFDIV_MASK 0x001f0000
+#define DDR_PLL_CONFIG_REFDIV_SET(x) \
+	(((x) << DDR_PLL_CONFIG_REFDIV_LSB) & DDR_PLL_CONFIG_REFDIV_MASK)
+#define DDR_PLL_CONFIG1_NINT_LSB 18
+#define DDR_PLL_CONFIG1_NINT_MASK 0x07fc0000
+#define DDR_PLL_CONFIG1_NINT_SET(x) \
+	(((x) << DDR_PLL_CONFIG1_NINT_LSB) & DDR_PLL_CONFIG1_NINT_MASK)
+#define DDR_PLL_DITHER1_DITHER_EN_LSB 31
+#define DDR_PLL_DITHER1_DITHER_EN_MASK 0x80000000
+#define DDR_PLL_DITHER1_DITHER_EN_SET(x) \
+	(((x) << DDR_PLL_DITHER1_DITHER_EN_LSB) & DDR_PLL_DITHER1_DITHER_EN_MASK)
+#define DDR_PLL_DITHER1_UPDATE_COUNT_LSB 27
+#define DDR_PLL_DITHER1_UPDATE_COUNT_MASK 0x78000000
+#define DDR_PLL_DITHER1_UPDATE_COUNT_SET(x) \
+	(((x) << DDR_PLL_DITHER1_UPDATE_COUNT_LSB) & DDR_PLL_DITHER1_UPDATE_COUNT_MASK)
+#define DDR_PLL_DITHER1_NFRAC_STEP_LSB 20
+#define DDR_PLL_DITHER1_NFRAC_STEP_MASK 0x07f00000
+#define DDR_PLL_DITHER1_NFRAC_STEP_SET(x) \
+	(((x) << DDR_PLL_DITHER1_NFRAC_STEP_LSB) & DDR_PLL_DITHER1_NFRAC_STEP_MASK)
+#define DDR_PLL_DITHER1_NFRAC_MIN_LSB 0
+#define DDR_PLL_DITHER1_NFRAC_MIN_MASK 0x0003ffff
+#define DDR_PLL_DITHER1_NFRAC_MIN_SET(x) \
+	(((x) << DDR_PLL_DITHER1_NFRAC_MIN_LSB) & DDR_PLL_DITHER1_NFRAC_MIN_MASK)
+#define DDR_PLL_DITHER2_NFRAC_MAX_LSB 0
+#define DDR_PLL_DITHER2_NFRAC_MAX_MASK 0x0003ffff
+#define DDR_PLL_DITHER2_NFRAC_MAX_SET(x) \
+	(((x) << DDR_PLL_DITHER2_NFRAC_MAX_LSB) & DDR_PLL_DITHER2_NFRAC_MAX_MASK)
+#define CPU_DDR_CLOCK_CONTROL_AHBCLK_FROM_DDRPLL_LSB 24
+#define CPU_DDR_CLOCK_CONTROL_AHBCLK_FROM_DDRPLL_MASK 0x01000000
+#define CPU_DDR_CLOCK_CONTROL_AHBCLK_FROM_DDRPLL_SET(x) \
+	(((x) << CPU_DDR_CLOCK_CONTROL_AHBCLK_FROM_DDRPLL_LSB) & CPU_DDR_CLOCK_CONTROL_AHBCLK_FROM_DDRPLL_MASK)
+#define CPU_DDR_CLOCK_CONTROL_CPU_DDR_CLK_FROM_CPUPLL_LSB 21
+#define CPU_DDR_CLOCK_CONTROL_CPU_DDR_CLK_FROM_CPUPLL_MASK 0x00200000
+#define CPU_DDR_CLOCK_CONTROL_CPU_DDR_CLK_FROM_CPUPLL_SET(x) \
+	(((x) << CPU_DDR_CLOCK_CONTROL_CPU_DDR_CLK_FROM_CPUPLL_LSB) & CPU_DDR_CLOCK_CONTROL_CPU_DDR_CLK_FROM_CPUPLL_MASK)
+#define CPU_DDR_CLOCK_CONTROL_CPU_DDR_CLK_FROM_DDRPLL_LSB 20
+#define CPU_DDR_CLOCK_CONTROL_CPU_DDR_CLK_FROM_DDRPLL_MASK 0x00100000
+#define CPU_DDR_CLOCK_CONTROL_CPU_DDR_CLK_FROM_DDRPLL_SET(x) \
+	(((x) << CPU_DDR_CLOCK_CONTROL_CPU_DDR_CLK_FROM_DDRPLL_LSB) & CPU_DDR_CLOCK_CONTROL_CPU_DDR_CLK_FROM_DDRPLL_MASK)
+#define CPU_DDR_CLOCK_CONTROL_AHB_POST_DIV_LSB 15
+#define CPU_DDR_CLOCK_CONTROL_AHB_POST_DIV_MASK 0x000f8000
+#define CPU_DDR_CLOCK_CONTROL_AHB_POST_DIV_SET(x) \
+	(((x) << CPU_DDR_CLOCK_CONTROL_AHB_POST_DIV_LSB) & CPU_DDR_CLOCK_CONTROL_AHB_POST_DIV_MASK)
+#define CPU_DDR_CLOCK_CONTROL_DDR_POST_DIV_LSB 10
+#define CPU_DDR_CLOCK_CONTROL_DDR_POST_DIV_MASK 0x00007c00
+#define CPU_DDR_CLOCK_CONTROL_DDR_POST_DIV_SET(x) \
+	(((x) << CPU_DDR_CLOCK_CONTROL_DDR_POST_DIV_LSB) & CPU_DDR_CLOCK_CONTROL_DDR_POST_DIV_MASK)
+#define CPU_DDR_CLOCK_CONTROL_CPU_POST_DIV_LSB 5
+#define CPU_DDR_CLOCK_CONTROL_CPU_POST_DIV_MASK 0x000003e0
+#define CPU_DDR_CLOCK_CONTROL_CPU_POST_DIV_SET(x) \
+	(((x) << CPU_DDR_CLOCK_CONTROL_CPU_POST_DIV_LSB) & CPU_DDR_CLOCK_CONTROL_CPU_POST_DIV_MASK)
+#define CPU_DDR_CLOCK_CONTROL_AHB_PLL_BYPASS_LSB 4
+#define CPU_DDR_CLOCK_CONTROL_AHB_PLL_BYPASS_MASK 0x00000010
+#define CPU_DDR_CLOCK_CONTROL_AHB_PLL_BYPASS_SET(x) \
+	(((x) << CPU_DDR_CLOCK_CONTROL_AHB_PLL_BYPASS_LSB) & CPU_DDR_CLOCK_CONTROL_AHB_PLL_BYPASS_MASK)
+#define CPU_DDR_CLOCK_CONTROL_DDR_PLL_BYPASS_LSB 3
+#define CPU_DDR_CLOCK_CONTROL_DDR_PLL_BYPASS_MASK 0x00000008
+#define CPU_DDR_CLOCK_CONTROL_DDR_PLL_BYPASS_SET(x) \
+	(((x) << CPU_DDR_CLOCK_CONTROL_DDR_PLL_BYPASS_LSB) & CPU_DDR_CLOCK_CONTROL_DDR_PLL_BYPASS_MASK)
+#define CPU_DDR_CLOCK_CONTROL_CPU_PLL_BYPASS_LSB 2
+#define CPU_DDR_CLOCK_CONTROL_CPU_PLL_BYPASS_MASK 0x00000004
+#define CPU_DDR_CLOCK_CONTROL_CPU_PLL_BYPASS_SET(x) \
+	(((x) << CPU_DDR_CLOCK_CONTROL_CPU_PLL_BYPASS_LSB) & CPU_DDR_CLOCK_CONTROL_CPU_PLL_BYPASS_MASK)
+
+#define CPU_PLL_CONFIG1_NINT_VAL CPU_PLL_CONFIG1_NINT_SET(0x1f)
+#define CPU_PLL_CONFIG_REF_DIV_VAL CPU_PLL_CONFIG_REFDIV_SET(0x1)
+#define CPU_PLL_CONFIG_RANGE_VAL CPU_PLL_CONFIG_RANGE_SET(0)
+#define CPU_PLL_CONFIG_OUT_DIV_VAL1 CPU_PLL_CONFIG_OUTDIV_SET(0)
+#define CPU_PLL_CONFIG_OUT_DIV_VAL2 CPU_PLL_CONFIG_OUTDIV_SET(0)
+#define CPU_PLL_DITHER1_VAL CPU_PLL_DITHER1_DITHER_EN_SET(0) | \
+	CPU_PLL_DITHER1_NFRAC_MIN_SET(0) | \
+	CPU_PLL_DITHER1_NFRAC_STEP_SET(0) | \
+	CPU_PLL_DITHER1_UPDATE_COUNT_SET(0x0)
+#define CPU_PLL_DITHER2_VAL CPU_PLL_DITHER2_NFRAC_MAX_SET(0x0)
+#define DDR_PLL_CONFIG1_NINT_VAL DDR_PLL_CONFIG1_NINT_SET(0x1a)
+#define DDR_PLL_CONFIG_REF_DIV_VAL DDR_PLL_CONFIG_REFDIV_SET(0x1)
+#define DDR_PLL_CONFIG_RANGE_VAL DDR_PLL_CONFIG_RANGE_SET(0)
+#define DDR_PLL_CONFIG_OUT_DIV_VAL1 DDR_PLL_CONFIG_OUTDIV_SET(0)
+#define DDR_PLL_CONFIG_OUT_DIV_VAL2 DDR_PLL_CONFIG_OUTDIV_SET(0)
+#define DDR_PLL_DITHER1_VAL DDR_PLL_DITHER1_DITHER_EN_SET(0) | \
+	DDR_PLL_DITHER1_NFRAC_MIN_SET(0) | \
+	DDR_PLL_DITHER1_NFRAC_STEP_SET(0) | \
+	DDR_PLL_DITHER1_UPDATE_COUNT_SET(0x0)
+#define DDR_PLL_DITHER2_VAL DDR_PLL_DITHER2_NFRAC_MAX_SET(0x0)
+#define AHB_CLK_FROM_DDR CPU_DDR_CLOCK_CONTROL_AHBCLK_FROM_DDRPLL_SET(0)
+#define CPU_AND_DDR_CLK_FROM_DDR \
+	CPU_DDR_CLOCK_CONTROL_CPU_DDR_CLK_FROM_DDRPLL_SET(0)
+#define CPU_AND_DDR_CLK_FROM_CPU \
+	CPU_DDR_CLOCK_CONTROL_CPU_DDR_CLK_FROM_CPUPLL_SET(0)
+#define CPU_DDR_CLOCK_CONTROL_AHB_DIV_VAL \
+	CPU_DDR_CLOCK_CONTROL_AHB_POST_DIV_SET(0x2)
+#define CPU_DDR_CLOCK_CONTROL_DDR_POST_DIV \
+	CPU_DDR_CLOCK_CONTROL_DDR_POST_DIV_SET(0)
+#define CPU_DDR_CLOCK_CONTROL_CPU_POST_DIV \
+	CPU_DDR_CLOCK_CONTROL_CPU_POST_DIV_SET(0)
+
+static inline void set_val(u32 _reg, u32 _mask, u32 _val)
+{
+	void __iomem *pll_regs = map_physmem(AR71XX_PLL_BASE,
+					     AR71XX_PLL_SIZE, MAP_NOCACHE);
+	writel((readl(pll_regs + _reg) & (~(_mask))) | _val, pll_regs + _reg);
+}
+
+#define cpu_pll_set(_mask, _val)	\
+	set_val(QCA956X_PLL_CPU_CONFIG_REG, _mask, _val)
+
+#define ddr_pll_set(_mask, _val)	\
+	set_val(QCA956X_PLL_DDR_CONFIG_REG, _mask, _val)
+
+#define cpu_ddr_control_set(_mask, _val)	\
+	set_val(QCA956X_PLL_CLK_CTRL_REG, _mask, _val)
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static u32 qca956x_get_xtal(void)
+{
+	u32 val;
+
+	val = ath79_get_bootstrap();
+	if (val & QCA956X_BOOTSTRAP_REF_CLK_40)
+		return 40000000;
+	else
+		return 25000000;
+}
+
+int get_serial_clock(void)
+{
+	return qca956x_get_xtal();
+}
+
+void qca956x_pll_init(void)
+{
+	void __iomem *srif_regs = map_physmem(QCA956X_SRIF_BASE,
+					      QCA956X_SRIF_SIZE, MAP_NOCACHE);
+	void __iomem *pll_regs = map_physmem(AR71XX_PLL_BASE,
+					     AR71XX_PLL_SIZE, MAP_NOCACHE);
+
+	/* 8.16.2 Baseband DPLL2 */
+	writel(PLL_SRIF_DPLL2_KI_SET(2) | PLL_SRIF_DPLL2_KD_SET(0xa) |
+		PLL_SRIF_DPLL2_PLL_PWD_SET(1) | PLL_SRIF_DPLL2_OUTDIV_SET(1) |
+		PLL_SRIF_DPLL2_PHASE_SHIFT_SET(6), srif_regs + QCA956X_SRIF_BB_DPLL2_REG);
+
+	/* 8.16.2 PCIE DPLL2 */
+	writel(PLL_SRIF_DPLL2_KI_SET(2) | PLL_SRIF_DPLL2_KD_SET(0xa) |
+		PLL_SRIF_DPLL2_PLL_PWD_SET(1) | PLL_SRIF_DPLL2_OUTDIV_SET(3) |
+		PLL_SRIF_DPLL2_PHASE_SHIFT_SET(6), srif_regs + QCA956X_SRIF_PCIE_DPLL2_REG);
+
+	/* 8.16.2 DDR DPLL2 */
+	writel(PLL_SRIF_DPLL2_KI_SET(2) | PLL_SRIF_DPLL2_KD_SET(0xa) |
+		PLL_SRIF_DPLL2_PLL_PWD_SET(1) | PLL_SRIF_DPLL2_PHASE_SHIFT_SET(6),
+		srif_regs + QCA956X_SRIF_DDR_DPLL2_REG);
+
+	/* 8.16.2 CPU DPLL2 */
+	writel(PLL_SRIF_DPLL2_KI_SET(1) | PLL_SRIF_DPLL2_KD_SET(7) |
+			  PLL_SRIF_DPLL2_PLL_PWD_SET(1) | PLL_SRIF_DPLL2_PHASE_SHIFT_SET(6),
+			  srif_regs + QCA956X_SRIF_CPU_DPLL2_REG);
+
+	/* pll_bypass_set */
+	cpu_ddr_control_set(CPU_DDR_CLOCK_CONTROL_CPU_PLL_BYPASS_MASK,
+			    CPU_DDR_CLOCK_CONTROL_CPU_PLL_BYPASS_SET(1));
+	cpu_ddr_control_set(CPU_DDR_CLOCK_CONTROL_DDR_PLL_BYPASS_MASK,
+			    CPU_DDR_CLOCK_CONTROL_DDR_PLL_BYPASS_SET(1));
+	cpu_ddr_control_set(CPU_DDR_CLOCK_CONTROL_AHB_PLL_BYPASS_MASK,
+			    CPU_DDR_CLOCK_CONTROL_AHB_PLL_BYPASS_SET(1));
+
+	/* init_cpu_pll */
+	cpu_pll_set(CPU_PLL_CONFIG_PLLPWD_MASK,  CPU_PLL_CONFIG_PLLPWD_SET(1));
+	cpu_pll_set(CPU_PLL_CONFIG_REFDIV_MASK, CPU_PLL_CONFIG_REF_DIV_VAL);
+	cpu_pll_set(CPU_PLL_CONFIG_RANGE_MASK, CPU_PLL_CONFIG_RANGE_VAL);
+	cpu_pll_set(CPU_PLL_CONFIG_OUTDIV_MASK, CPU_PLL_CONFIG_OUT_DIV_VAL1);
+	set_val(QCA956X_PLL_CPU_CONFIG1_REG, CPU_PLL_CONFIG1_NINT_MASK, \
+		CPU_PLL_CONFIG1_NINT_VAL);
+
+	/* init_ddr_pll */
+	ddr_pll_set(DDR_PLL_CONFIG_PLLPWD_MASK,  DDR_PLL_CONFIG_PLLPWD_SET(1));
+	ddr_pll_set(DDR_PLL_CONFIG_REFDIV_MASK, DDR_PLL_CONFIG_REF_DIV_VAL);
+	ddr_pll_set(DDR_PLL_CONFIG_RANGE_MASK, DDR_PLL_CONFIG_RANGE_VAL);
+	ddr_pll_set(DDR_PLL_CONFIG_OUTDIV_MASK, DDR_PLL_CONFIG_OUT_DIV_VAL1);
+	set_val(QCA956X_PLL_DDR_CONFIG1_REG, DDR_PLL_CONFIG1_NINT_MASK,
+		DDR_PLL_CONFIG1_NINT_VAL);
+
+	/* init_ahb_pll */
+	writel(CPU_DDR_CLOCK_CONTROL_AHB_DIV_VAL | AHB_CLK_FROM_DDR |
+		CPU_AND_DDR_CLK_FROM_DDR | CPU_AND_DDR_CLK_FROM_CPU |
+		CPU_DDR_CLOCK_CONTROL_DDR_POST_DIV | CPU_DDR_CLOCK_CONTROL_CPU_POST_DIV |
+		CPU_DDR_CLOCK_CONTROL_CPU_PLL_BYPASS_SET(1) |
+		CPU_DDR_CLOCK_CONTROL_DDR_PLL_BYPASS_SET(1) |
+		CPU_DDR_CLOCK_CONTROL_AHB_PLL_BYPASS_SET(1), pll_regs + QCA956X_PLL_CLK_CTRL_REG);
+
+	/* ddr_pll_dither_unset */
+	writel(DDR_PLL_DITHER1_VAL, pll_regs + QCA956X_PLL_DDR_DIT_FRAC_REG);
+	writel(DDR_PLL_DITHER2_VAL, pll_regs + QCA956X_PLL_DDR_DIT2_FRAC_REG);
+
+	/* cpu_pll_dither_unset */
+	writel(CPU_PLL_DITHER1_VAL, pll_regs + QCA956X_PLL_CPU_DIT_FRAC_REG);
+	writel(CPU_PLL_DITHER2_VAL, pll_regs + QCA956X_PLL_CPU_DIT2_FRAC_REG);
+
+	/* pll_pwd_unset */
+	cpu_pll_set(CPU_PLL_CONFIG_PLLPWD_MASK, CPU_PLL_CONFIG_PLLPWD_SET(0));
+	ddr_pll_set(DDR_PLL_CONFIG_PLLPWD_MASK, DDR_PLL_CONFIG_PLLPWD_SET(0));
+
+	/* outdiv_unset */
+	cpu_pll_set(CPU_PLL_CONFIG_OUTDIV_MASK, CPU_PLL_CONFIG_OUT_DIV_VAL2);
+	ddr_pll_set(DDR_PLL_CONFIG_OUTDIV_MASK, DDR_PLL_CONFIG_OUT_DIV_VAL2);
+
+	/* pll_bypass_unset */
+	cpu_ddr_control_set(CPU_DDR_CLOCK_CONTROL_CPU_PLL_BYPASS_MASK,
+			    CPU_DDR_CLOCK_CONTROL_CPU_PLL_BYPASS_SET(0));
+	cpu_ddr_control_set(CPU_DDR_CLOCK_CONTROL_DDR_PLL_BYPASS_MASK,
+			    CPU_DDR_CLOCK_CONTROL_DDR_PLL_BYPASS_SET(0));
+	cpu_ddr_control_set(CPU_DDR_CLOCK_CONTROL_AHB_PLL_BYPASS_MASK,
+			    CPU_DDR_CLOCK_CONTROL_AHB_PLL_BYPASS_SET(0));
+
+	while (readl(pll_regs + QCA956X_PLL_CPU_CONFIG_REG) & 0x8000000)
+		/* NOP */;
+
+	while (readl(pll_regs + QCA956X_PLL_DDR_CONFIG_REG) & 0x8000000)
+		/* NOP */;
+}
+
+int get_clocks(void)
+{
+	void __iomem *regs;
+	u32 ref_rate, cpu_rate, ddr_rate, ahb_rate;
+	u32 out_div, ref_div, postdiv, nint, hfrac, lfrac, clk_ctrl;
+	u32 pll, cpu_pll, ddr_pll, misc;
+
+	/*
+	 * QCA956x timer init workaround has to be applied right before setting
+	 * up the clock. Else, there will be no jiffies
+	 */
+	regs = map_physmem(AR71XX_RESET_BASE, AR71XX_RESET_SIZE,
+			   MAP_NOCACHE);
+	misc = readl(regs + AR71XX_RESET_REG_MISC_INT_ENABLE);
+	misc |= MISC_INT_MIPS_SI_TIMERINT_MASK;
+	writel(misc, regs + AR71XX_RESET_REG_MISC_INT_ENABLE);
+
+	regs = map_physmem(AR71XX_PLL_BASE, AR71XX_PLL_SIZE,
+			   MAP_NOCACHE);
+	pll = readl(regs + QCA956X_PLL_CPU_CONFIG_REG);
+	out_div = (pll >> QCA956X_PLL_CPU_CONFIG_OUTDIV_SHIFT) &
+			  QCA956X_PLL_CPU_CONFIG_OUTDIV_MASK;
+	ref_div = (pll >> QCA956X_PLL_CPU_CONFIG_REFDIV_SHIFT) &
+			  QCA956X_PLL_CPU_CONFIG_REFDIV_MASK;
+
+	pll = readl(regs + QCA956X_PLL_CPU_CONFIG1_REG);
+	nint = (pll >> QCA956X_PLL_CPU_CONFIG1_NINT_SHIFT) &
+			  QCA956X_PLL_CPU_CONFIG1_NINT_MASK;
+	hfrac = (pll >> QCA956X_PLL_CPU_CONFIG1_NFRAC_H_SHIFT) &
+			  QCA956X_PLL_CPU_CONFIG1_NFRAC_H_MASK;
+	lfrac = (pll >> QCA956X_PLL_CPU_CONFIG1_NFRAC_L_SHIFT) &
+			  QCA956X_PLL_CPU_CONFIG1_NFRAC_L_MASK;
+
+	ref_rate = qca956x_get_xtal();
+
+	cpu_pll = nint * ref_rate / ref_div;
+	cpu_pll += (lfrac * ref_rate) / ((ref_div * 25) << 13);
+	cpu_pll += (hfrac >> 13) * ref_rate / ref_div;
+	cpu_pll /= (1 << out_div);
+
+	pll = readl(regs + QCA956X_PLL_DDR_CONFIG_REG);
+	out_div = (pll >> QCA956X_PLL_DDR_CONFIG_OUTDIV_SHIFT) &
+			  QCA956X_PLL_DDR_CONFIG_OUTDIV_MASK;
+	ref_div = (pll >> QCA956X_PLL_DDR_CONFIG_REFDIV_SHIFT) &
+			  QCA956X_PLL_DDR_CONFIG_REFDIV_MASK;
+	pll = readl(regs + QCA956X_PLL_DDR_CONFIG1_REG);
+	nint = (pll >> QCA956X_PLL_DDR_CONFIG1_NINT_SHIFT) &
+		QCA956X_PLL_DDR_CONFIG1_NINT_MASK;
+	hfrac = (pll >> QCA956X_PLL_DDR_CONFIG1_NFRAC_H_SHIFT) &
+		QCA956X_PLL_DDR_CONFIG1_NFRAC_H_MASK;
+	lfrac = (pll >> QCA956X_PLL_DDR_CONFIG1_NFRAC_L_SHIFT) &
+		QCA956X_PLL_DDR_CONFIG1_NFRAC_L_MASK;
+
+	ddr_pll = nint * ref_rate / ref_div;
+	ddr_pll += (lfrac * ref_rate) / ((ref_div * 25) << 13);
+	ddr_pll += (hfrac >> 13) * ref_rate / ref_div;
+	ddr_pll /= (1 << out_div);
+
+	clk_ctrl = readl(regs + QCA956X_PLL_CLK_CTRL_REG);
+
+	postdiv = (clk_ctrl >> QCA956X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT) &
+		  QCA956X_PLL_CLK_CTRL_CPU_POST_DIV_MASK;
+
+	if (clk_ctrl & QCA956X_PLL_CLK_CTRL_CPU_PLL_BYPASS)
+		cpu_rate = ref_rate;
+	else if (clk_ctrl & QCA956X_PLL_CLK_CTRL_CPU_DDRCLK_FROM_CPUPLL)
+		cpu_rate = ddr_pll / (postdiv + 1);
+	else
+		cpu_rate = cpu_pll / (postdiv + 1);
+
+	postdiv = (clk_ctrl >> QCA956X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT) &
+		  QCA956X_PLL_CLK_CTRL_DDR_POST_DIV_MASK;
+
+	if (clk_ctrl & QCA956X_PLL_CLK_CTRL_DDR_PLL_BYPASS)
+		ddr_rate = ref_rate;
+	else if (clk_ctrl & QCA956X_PLL_CLK_CTRL_CPU_DDRCLK_FROM_DDRPLL)
+		ddr_rate = cpu_pll / (postdiv + 1);
+	else
+		ddr_rate = ddr_pll / (postdiv + 1);
+
+	postdiv = (clk_ctrl >> QCA956X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT) &
+		  QCA956X_PLL_CLK_CTRL_AHB_POST_DIV_MASK;
+
+	if (clk_ctrl & QCA956X_PLL_CLK_CTRL_AHB_PLL_BYPASS)
+		ahb_rate = ref_rate;
+	else if (clk_ctrl & QCA956X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL)
+		ahb_rate = ddr_pll / (postdiv + 1);
+	else
+		ahb_rate = cpu_pll / (postdiv + 1);
+
+	gd->cpu_clk = cpu_rate;
+	gd->mem_clk = ddr_rate;
+	gd->bus_clk = ahb_rate;
+
+	debug("cpu_clk=%u, ddr_clk=%u, bus_clk=%u\n",
+	      cpu_rate, ddr_rate, ahb_rate);
+
+	return 0;
+}
+
+ulong get_bus_freq(ulong dummy)
+{
+	if (!gd->bus_clk)
+		get_clocks();
+	return gd->bus_clk;
+}
+
+ulong get_ddr_freq(ulong dummy)
+{
+	if (!gd->mem_clk)
+		get_clocks();
+	return gd->mem_clk;
+}
diff --git a/arch/mips/mach-ath79/qca956x/cpu.c b/arch/mips/mach-ath79/qca956x/cpu.c
new file mode 100644
index 0000000..08a8c84
--- /dev/null
+++ b/arch/mips/mach-ath79/qca956x/cpu.c
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Rosy Song <rosysong@rosinson.com>
+ */
+
+#include <common.h>
+
+/* The lowlevel_init() is not needed on QCA956X */
+void lowlevel_init(void) {}
diff --git a/arch/mips/mach-ath79/qca956x/ddr.c b/arch/mips/mach-ath79/qca956x/ddr.c
new file mode 100644
index 0000000..fb22304
--- /dev/null
+++ b/arch/mips/mach-ath79/qca956x/ddr.c
@@ -0,0 +1,308 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Rosy Song <rosysong@rosinson.com>
+ *
+ * Based on QSDK
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/addrspace.h>
+#include <asm/types.h>
+#include <mach/ar71xx_regs.h>
+#include <mach/ath79.h>
+
+#define DDR_FSM_WAIT_CTRL_VAL 0xa12
+#define DDR_CTL_CONFIG_SRAM_TSEL_LSB 30
+#define DDR_CTL_CONFIG_SRAM_TSEL_MASK 0xc0000000
+#define DDR_CTL_CONFIG_SRAM_TSEL_SET(x) \
+	(((x) << DDR_CTL_CONFIG_SRAM_TSEL_LSB) & DDR_CTL_CONFIG_SRAM_TSEL_MASK)
+#define DDR_CTL_CONFIG_GE0_SRAM_SYNC_LSB 20
+#define DDR_CTL_CONFIG_GE0_SRAM_SYNC_MASK 0x00100000
+#define DDR_CTL_CONFIG_GE0_SRAM_SYNC_SET(x) \
+	(((x) << DDR_CTL_CONFIG_GE0_SRAM_SYNC_LSB) & DDR_CTL_CONFIG_GE0_SRAM_SYNC_MASK)
+#define DDR_CTL_CONFIG_GE1_SRAM_SYNC_LSB 19
+#define DDR_CTL_CONFIG_GE1_SRAM_SYNC_MASK 0x00080000
+#define DDR_CTL_CONFIG_GE1_SRAM_SYNC_SET(x) \
+	(((x) << DDR_CTL_CONFIG_GE1_SRAM_SYNC_LSB) & DDR_CTL_CONFIG_GE1_SRAM_SYNC_MASK)
+#define DDR_CTL_CONFIG_USB_SRAM_SYNC_LSB 18
+#define DDR_CTL_CONFIG_USB_SRAM_SYNC_MASK 0x00040000
+#define DDR_CTL_CONFIG_USB_SRAM_SYNC_SET(x) \
+	(((x) << DDR_CTL_CONFIG_USB_SRAM_SYNC_LSB) & DDR_CTL_CONFIG_USB_SRAM_SYNC_MASK)
+#define DDR_CTL_CONFIG_PCIE_SRAM_SYNC_LSB 17
+#define DDR_CTL_CONFIG_PCIE_SRAM_SYNC_MASK 0x00020000
+#define DDR_CTL_CONFIG_PCIE_SRAM_SYNC_SET(x) \
+	(((x) << DDR_CTL_CONFIG_PCIE_SRAM_SYNC_LSB) & DDR_CTL_CONFIG_PCIE_SRAM_SYNC_MASK)
+#define DDR_CTL_CONFIG_WMAC_SRAM_SYNC_LSB 16
+#define DDR_CTL_CONFIG_WMAC_SRAM_SYNC_MASK 0x00010000
+#define DDR_CTL_CONFIG_WMAC_SRAM_SYNC_SET(x) \
+	(((x) << DDR_CTL_CONFIG_WMAC_SRAM_SYNC_LSB) & DDR_CTL_CONFIG_WMAC_SRAM_SYNC_MASK)
+#define DDR_CTL_CONFIG_MISC_SRC1_SRAM_SYNC_LSB 15
+#define DDR_CTL_CONFIG_MISC_SRC1_SRAM_SYNC_MASK 0x00008000
+#define DDR_CTL_CONFIG_MISC_SRC1_SRAM_SYNC_SET(x) \
+	(((x) << DDR_CTL_CONFIG_MISC_SRC1_SRAM_SYNC_LSB) & DDR_CTL_CONFIG_MISC_SRC1_SRAM_SYNC_MASK)
+#define DDR_CTL_CONFIG_MISC_SRC2_SRAM_SYNC_LSB 14
+#define DDR_CTL_CONFIG_MISC_SRC2_SRAM_SYNC_MASK 0x00004000
+#define DDR_CTL_CONFIG_MISC_SRC2_SRAM_SYNC_SET(x) \
+	(((x) << DDR_CTL_CONFIG_MISC_SRC2_SRAM_SYNC_LSB) & DDR_CTL_CONFIG_MISC_SRC2_SRAM_SYNC_MASK)
+#define DDR_CTL_CONFIG_PAD_DDR2_SEL_LSB 6
+#define DDR_CTL_CONFIG_PAD_DDR2_SEL_MASK 0x00000040
+#define DDR_CTL_CONFIG_PAD_DDR2_SEL_SET(x) \
+	(((x) << DDR_CTL_CONFIG_PAD_DDR2_SEL_LSB) & DDR_CTL_CONFIG_PAD_DDR2_SEL_MASK)
+#define DDR_CTL_CONFIG_CPU_DDR_SYNC_LSB 2
+#define DDR_CTL_CONFIG_CPU_DDR_SYNC_MASK 0x00000004
+#define DDR_CTL_CONFIG_CPU_DDR_SYNC_SET(x) \
+	(((x) << DDR_CTL_CONFIG_CPU_DDR_SYNC_LSB) & DDR_CTL_CONFIG_CPU_DDR_SYNC_MASK)
+#define DDR_CTL_CONFIG_HALF_WIDTH_LSB 1
+#define DDR_CTL_CONFIG_HALF_WIDTH_MASK 0x00000002
+#define DDR_CTL_CONFIG_HALF_WIDTH_SET(x) \
+	(((x) << DDR_CTL_CONFIG_HALF_WIDTH_LSB) & DDR_CTL_CONFIG_HALF_WIDTH_MASK)
+#define DDR_CONFIG_CAS_LATENCY_MSB_LSB 31
+#define DDR_CONFIG_CAS_LATENCY_MSB_MASK 0x80000000
+#define DDR_CONFIG_CAS_LATENCY_MSB_SET(x) \
+	(((x) << DDR_CONFIG_CAS_LATENCY_MSB_LSB) & DDR_CONFIG_CAS_LATENCY_MSB_MASK)
+#define DDR_CONFIG_OPEN_PAGE_LSB 30
+#define DDR_CONFIG_OPEN_PAGE_MASK 0x40000000
+#define DDR_CONFIG_OPEN_PAGE_SET(x) \
+	(((x) << DDR_CONFIG_OPEN_PAGE_LSB) & DDR_CONFIG_OPEN_PAGE_MASK)
+#define DDR_CONFIG_CAS_LATENCY_LSB 27
+#define DDR_CONFIG_CAS_LATENCY_MASK 0x38000000
+#define DDR_CONFIG_CAS_LATENCY_SET(x) \
+	(((x) << DDR_CONFIG_CAS_LATENCY_LSB) & DDR_CONFIG_CAS_LATENCY_MASK)
+#define DDR_CONFIG_TMRD_LSB 23
+#define DDR_CONFIG_TMRD_MASK 0x07800000
+#define DDR_CONFIG_TMRD_SET(x) \
+	(((x) << DDR_CONFIG_TMRD_LSB) & DDR_CONFIG_TMRD_MASK)
+#define DDR_CONFIG_TRFC_LSB 17
+#define DDR_CONFIG_TRFC_MASK 0x007e0000
+#define DDR_CONFIG_TRFC_SET(x) \
+	(((x) << DDR_CONFIG_TRFC_LSB) & DDR_CONFIG_TRFC_MASK)
+#define DDR_CONFIG_TRRD_LSB 13
+#define DDR_CONFIG_TRRD_MASK 0x0001e000
+#define DDR_CONFIG_TRRD_SET(x) \
+	(((x) << DDR_CONFIG_TRRD_LSB) & DDR_CONFIG_TRRD_MASK)
+#define DDR_CONFIG_TRP_LSB 9
+#define DDR_CONFIG_TRP_MASK 0x00001e00
+#define DDR_CONFIG_TRP_SET(x) \
+	(((x) << DDR_CONFIG_TRP_LSB) & DDR_CONFIG_TRP_MASK)
+#define DDR_CONFIG_TRCD_LSB 5
+#define DDR_CONFIG_TRCD_MASK 0x000001e0
+#define DDR_CONFIG_TRCD_SET(x) \
+	(((x) << DDR_CONFIG_TRCD_LSB) & DDR_CONFIG_TRCD_MASK)
+#define DDR_CONFIG_TRAS_LSB 0
+#define DDR_CONFIG_TRAS_MASK 0x0000001f
+#define DDR_CONFIG_TRAS_SET(x) \
+	(((x) << DDR_CONFIG_TRAS_LSB) & DDR_CONFIG_TRAS_MASK)
+#define DDR_CONFIG2_HALF_WIDTH_LOW_LSB 31
+#define DDR_CONFIG2_HALF_WIDTH_LOW_MASK 0x80000000
+#define DDR_CONFIG2_HALF_WIDTH_LOW_SET(x) \
+	(((x) << DDR_CONFIG2_HALF_WIDTH_LOW_LSB) & DDR_CONFIG2_HALF_WIDTH_LOW_MASK)
+#define DDR_CONFIG2_SWAP_A26_A27_LSB 30
+#define DDR_CONFIG2_SWAP_A26_A27_MASK 0x40000000
+#define DDR_CONFIG2_SWAP_A26_A27_SET(x) \
+	(((x) << DDR_CONFIG2_SWAP_A26_A27_LSB) & DDR_CONFIG2_SWAP_A26_A27_MASK)
+#define DDR_CONFIG2_GATE_OPEN_LATENCY_LSB 26
+#define DDR_CONFIG2_GATE_OPEN_LATENCY_MASK 0x3c000000
+#define DDR_CONFIG2_GATE_OPEN_LATENCY_SET(x) \
+	(((x) << DDR_CONFIG2_GATE_OPEN_LATENCY_LSB) & DDR_CONFIG2_GATE_OPEN_LATENCY_MASK)
+#define DDR_CONFIG2_TWTR_LSB 21
+#define DDR_CONFIG2_TWTR_MASK 0x03e00000
+#define DDR_CONFIG2_TWTR_SET(x) \
+	(((x) << DDR_CONFIG2_TWTR_LSB) & DDR_CONFIG2_TWTR_MASK)
+#define DDR_CONFIG2_TRTP_LSB 17
+#define DDR_CONFIG2_TRTP_MASK 0x001e0000
+#define DDR_CONFIG2_TRTP_SET(x) \
+	(((x) << DDR_CONFIG2_TRTP_LSB) & DDR_CONFIG2_TRTP_MASK)
+#define DDR_CONFIG2_TRTW_LSB 12
+#define DDR_CONFIG2_TRTW_MASK 0x0001f000
+#define DDR_CONFIG2_TRTW_SET(x) \
+	(((x) << DDR_CONFIG2_TRTW_LSB) & DDR_CONFIG2_TRTW_MASK)
+#define DDR_CONFIG2_TWR_LSB 8
+#define DDR_CONFIG2_TWR_MASK 0x00000f00
+#define DDR_CONFIG2_TWR_SET(x) \
+	(((x) << DDR_CONFIG2_TWR_LSB) & DDR_CONFIG2_TWR_MASK)
+#define DDR_CONFIG2_CKE_LSB 7
+#define DDR_CONFIG2_CKE_MASK 0x00000080
+#define DDR_CONFIG2_CKE_SET(x) \
+	(((x) << DDR_CONFIG2_CKE_LSB) & DDR_CONFIG2_CKE_MASK)
+#define DDR_CONFIG2_CNTL_OE_EN_LSB 5
+#define DDR_CONFIG2_CNTL_OE_EN_MASK 0x00000020
+#define DDR_CONFIG2_CNTL_OE_EN_SET(x) \
+	(((x) << DDR_CONFIG2_CNTL_OE_EN_LSB) & DDR_CONFIG2_CNTL_OE_EN_MASK)
+#define DDR_CONFIG2_BURST_LENGTH_LSB 0
+#define DDR_CONFIG2_BURST_LENGTH_MASK 0x0000000f
+#define DDR_CONFIG2_BURST_LENGTH_SET(x) \
+	(((x) << DDR_CONFIG2_BURST_LENGTH_LSB) & DDR_CONFIG2_BURST_LENGTH_MASK)
+#define RST_BOOTSTRAP_ADDRESS		0x180600b0
+#define PMU2_SWREGMSB_LSB 22
+#define PMU2_SWREGMSB_MASK 0xffc00000
+#define PMU2_SWREGMSB_SET(x) \
+	(((x) << PMU2_SWREGMSB_LSB) & PMU2_SWREGMSB_MASK)
+#define PMU2_PGM_LSB 21
+#define PMU2_PGM_MASK 0x00200000
+#define PMU2_PGM_SET(x) \
+	(((x) << PMU2_PGM_LSB) & PMU2_PGM_MASK)
+
+#define CPU_DDR_SYNC_MODE DDR_CTL_CONFIG_CPU_DDR_SYNC_SET(0)
+
+/*
+* DDR2                      DDR1
+* 0x40c3   25MHz            0x4186   25Mhz
+* 0x4138   40MHz            0x4270   40Mhz
+*/
+#define CFG_DDR2_REFRESH_VAL 0x40c3
+#define CFG_DDR2_CONFIG_VAL DDR_CONFIG_CAS_LATENCY_MSB_SET(0x1) | \
+	DDR_CONFIG_OPEN_PAGE_SET(0x1) | DDR_CONFIG_CAS_LATENCY_SET(0x4) | \
+	DDR_CONFIG_TMRD_SET(0x6) | DDR_CONFIG_TRFC_SET(0x16) | \
+	DDR_CONFIG_TRRD_SET(0x7) | DDR_CONFIG_TRP_SET(0xb) | \
+	DDR_CONFIG_TRCD_SET(0xb) | DDR_CONFIG_TRAS_SET(0)
+#define CFG_DDR2_CONFIG2_VAL DDR_CONFIG2_HALF_WIDTH_LOW_SET(0x1) | \
+	DDR_CONFIG2_SWAP_A26_A27_SET(0x0) | DDR_CONFIG2_GATE_OPEN_LATENCY_SET(0xa) | \
+	DDR_CONFIG2_TWTR_SET(0x16) | DDR_CONFIG2_TRTP_SET(0xa) | \
+	DDR_CONFIG2_TRTW_SET(0xe) | DDR_CONFIG2_TWR_SET(0x2) | \
+	DDR_CONFIG2_CKE_SET(0x1) | DDR_CONFIG2_CNTL_OE_EN_SET(0x1) | \
+	DDR_CONFIG2_BURST_LENGTH_SET(0x8)
+
+#define CFG_DDR2_CONFIG3_VAL 0x0000000e
+#define CFG_DDR2_EXT_MODE_VAL1 0x782
+#define CFG_DDR2_EXT_MODE_VAL2 0x402
+#define CFG_DDR2_MODE_VAL_INIT 0xb53
+#define CFG_DDR2_MODE_VAL 0xa53
+#define CFG_DDR2_TAP_VAL 0x10
+#define CFG_DDR2_EN_TWL_VAL 0x00001e91
+#define CFG_DDR2_RD_DATA_THIS_CYCLE_VAL_16 0xffff
+
+#define CFG_DDR_CTL_CONFIG DDR_CTL_CONFIG_SRAM_TSEL_SET(0x1) | \
+	DDR_CTL_CONFIG_GE0_SRAM_SYNC_SET(0x1) | \
+	DDR_CTL_CONFIG_GE1_SRAM_SYNC_SET(0x1) | \
+	DDR_CTL_CONFIG_USB_SRAM_SYNC_SET(0x1) | \
+	DDR_CTL_CONFIG_PCIE_SRAM_SYNC_SET(0x1) | \
+	DDR_CTL_CONFIG_WMAC_SRAM_SYNC_SET(0x1) | \
+	DDR_CTL_CONFIG_MISC_SRC1_SRAM_SYNC_SET(0x1) | \
+	DDR_CTL_CONFIG_MISC_SRC2_SRAM_SYNC_SET(0x1)
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void qca956x_ddr_init(void)
+{
+	u32 ddr_config, ddr_config2, ddr_config3, mod_val, \
+		mod_val_init, cycle_val, tap_val, ctl_config;
+	void __iomem *ddr_regs = map_physmem(AR71XX_DDR_CTRL_BASE, AR71XX_DDR_CTRL_SIZE,
+			       MAP_NOCACHE);
+	void __iomem *srif_regs = map_physmem(QCA956X_SRIF_BASE, QCA956X_SRIF_SIZE,
+			       MAP_NOCACHE);
+
+	ddr_config = CFG_DDR2_CONFIG_VAL;
+	ddr_config2 = CFG_DDR2_CONFIG2_VAL;
+	ddr_config3 = CFG_DDR2_CONFIG3_VAL;
+	mod_val_init = CFG_DDR2_MODE_VAL_INIT;
+	mod_val = CFG_DDR2_MODE_VAL;
+	tap_val = CFG_DDR2_TAP_VAL;
+	cycle_val = CFG_DDR2_RD_DATA_THIS_CYCLE_VAL_16;
+	ctl_config = CFG_DDR_CTL_CONFIG | DDR_CTL_CONFIG_PAD_DDR2_SEL_SET(0x1) |
+			 DDR_CTL_CONFIG_HALF_WIDTH_SET(0x1) | CPU_DDR_SYNC_MODE;
+
+	writel(0x10, ddr_regs + AR71XX_DDR_REG_CONTROL);
+	udelay(10);
+
+	writel(0x20, ddr_regs + AR71XX_DDR_REG_CONTROL);
+	udelay(10);
+
+	writel(ctl_config, ddr_regs + QCA956X_DDR_REG_CTL_CONF);
+	udelay(10);
+
+	writel(cycle_val, ddr_regs + AR71XX_DDR_REG_RD_CYCLE);
+	udelay(100);
+
+	writel(0x74444444, ddr_regs + QCA956X_DDR_REG_BURST);
+	udelay(100);
+
+	writel(0x44444444, ddr_regs + QCA956X_DDR_REG_BURST2);
+	udelay(100);
+
+	writel(DDR_FSM_WAIT_CTRL_VAL, ddr_regs + QCA956X_DDR_REG_FSM_WAIT_CTRL);
+	udelay(100);
+
+	writel(0xfffff, ddr_regs + QCA956X_DDR_REG_TIMEOUT_MAX);
+	udelay(100);
+
+	writel(ddr_config, ddr_regs + AR71XX_DDR_REG_CONFIG);
+	udelay(100);
+
+	writel(ddr_config2, ddr_regs + AR71XX_DDR_REG_CONFIG2);
+	udelay(100);
+
+	writel(ddr_config3, ddr_regs + QCA956X_DDR_REG_DDR3_CONFIG);
+	udelay(100);
+
+	writel(CFG_DDR2_EN_TWL_VAL, ddr_regs + QCA956X_DDR_REG_DDR2_CONFIG);
+	udelay(100);
+
+	writel(ddr_config2 | 0x80, ddr_regs + AR71XX_DDR_REG_CONFIG2);	/* CKE Enable */
+	udelay(100);
+
+	writel(0x8, ddr_regs + AR71XX_DDR_REG_CONTROL);	/* Precharge */
+	udelay(10);
+
+	writel(0, ddr_regs + QCA956X_DDR_REG_DDR2_EMR2);
+	writel(0x10, ddr_regs + AR71XX_DDR_REG_CONTROL);	/* EMR2 */
+	udelay(10);
+
+	writel(0, ddr_regs + QCA956X_DDR_REG_DDR2_EMR3);
+	writel(0x20, ddr_regs + AR71XX_DDR_REG_CONTROL);	/* EMR3 */
+	udelay(10);
+
+	/* EMR DLL enable, Reduced Driver Impedance control, Differential DQS disabled */
+	writel(CFG_DDR2_EXT_MODE_VAL2, ddr_regs + AR71XX_DDR_REG_EMR);
+	udelay(100);
+
+	writel(0x2, ddr_regs + AR71XX_DDR_REG_CONTROL); /* EMR write */
+	udelay(10);
+
+	writel(mod_val_init, ddr_regs + AR71XX_DDR_REG_MODE);
+	udelay(1000);
+
+	writel(0x1, ddr_regs + AR71XX_DDR_REG_CONTROL);	/* MR Write */
+	udelay(10);
+
+	writel(0x8, ddr_regs + AR71XX_DDR_REG_CONTROL);	/* Precharge */
+	udelay(10);
+
+	writel(0x4, ddr_regs + AR71XX_DDR_REG_CONTROL);	/* Auto Refresh */
+	udelay(10);
+
+	writel(0x4, ddr_regs + AR71XX_DDR_REG_CONTROL);	/* Auto Refresh */
+	udelay(10);
+
+	/* Issue MRS to remove DLL out-of-reset */
+	writel(mod_val, ddr_regs + AR71XX_DDR_REG_MODE);
+	udelay(100);
+
+	writel(0x1, ddr_regs + AR71XX_DDR_REG_CONTROL); /* MR write */
+	udelay(100);
+
+	writel(CFG_DDR2_EXT_MODE_VAL1, ddr_regs + AR71XX_DDR_REG_EMR);
+	udelay(100);
+
+	writel(0x2, ddr_regs + AR71XX_DDR_REG_CONTROL); /* EMR write */
+	udelay(100);
+
+	writel(CFG_DDR2_EXT_MODE_VAL2, ddr_regs + AR71XX_DDR_REG_EMR);
+	udelay(100);
+
+	writel(0x2, ddr_regs + AR71XX_DDR_REG_CONTROL); /* EMR write */
+	udelay(100);
+
+	writel(CFG_DDR2_REFRESH_VAL, ddr_regs + AR71XX_DDR_REG_REFRESH);
+	udelay(100);
+
+	writel(tap_val, ddr_regs + AR71XX_DDR_REG_TAP_CTRL0);
+	writel(tap_val, ddr_regs + AR71XX_DDR_REG_TAP_CTRL1);
+	writel(tap_val, ddr_regs + QCA956X_DDR_REG_TAP_CTRL2);
+	writel(tap_val, ddr_regs + QCA956X_DDR_REG_TAP_CTRL3);
+
+	writel(0x633c8176, srif_regs + QCA956X_SRIF_PMU1_REG);
+	/* Set DDR2 Voltage to 1.8 volts */
+	writel(PMU2_SWREGMSB_SET(0x40) | PMU2_PGM_SET(0x1),
+	       srif_regs + QCA956X_SRIF_PMU2_REG);
+}
diff --git a/arch/mips/mach-ath79/qca956x/qca956x-ddr-tap.S b/arch/mips/mach-ath79/qca956x/qca956x-ddr-tap.S
new file mode 100644
index 0000000..db54b57
--- /dev/null
+++ b/arch/mips/mach-ath79/qca956x/qca956x-ddr-tap.S
@@ -0,0 +1,193 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Rosy Song <rosysong@rosinson.com>
+ *
+ * Based on QSDK
+ */
+
+#include <config.h>
+#include <asm/asm.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include <mach/ar71xx_regs.h>
+
+    .set noreorder
+
+LEAF(ddr_tap_tuning)
+	li	a0, 0xbd001f00
+	sw	zero, 0x0(a0)			/* Place where the tap values are saved and used for SWEEP */
+	sw	zero, 0x4(a0)			/* Place where the number of passing taps are saved. */
+	sw	zero, 0x14(a0)		/* Place where the last pass tap value is stored */
+	li	a1, 0xaa55aa55		/* Indicates that the First pass tap value is not found */
+	sw	a1, 0x10(a0)		/* Place where the First pass tap value is stored */
+	 nop
+
+	li	a0, CKSEG1ADDR(AR71XX_RESET_BASE)		/* RESET_BASE_ADDRESS */
+	lw	a1, 0x1c(a0)		/* Reading the RST_RESET_ADDRESS */
+	li	a2, 0x08000000		/* Setting the RST_RESET_RTC_RESET */
+	or	a1, a1, a2
+	sw	a1, 0x1c(a0)
+
+	li	a3, 0xffffffff
+	xor	a2, a2, a3
+	and	a1, a1, a2
+	sw	a1, 0x1c(a0)		/* Taking the RTC out of RESET */
+	 nop
+
+	li	a0, CKSEG1ADDR(QCA956X_RTC_BASE)		/* RTC_BASE_ADDRESS */
+	li	a1, 0x1
+	sw	a1, 0x0040(a0)		/* RTC_SYNC_RESET_ADDRESS */
+
+	li	a2, 0x2
+
+_poll_for_RTC_ON:
+	lw	a1, 0x0044(a0)		/* RTC_SYNC_STATUS_ADDRESS */
+	and	a1, a2, a1
+	bne	a1, a2, _poll_for_RTC_ON
+	  nop
+
+_CHANGE_TAPS:
+	li	t0, 0xbd001f00		/* Read the current value of the TAP for programming */
+	lw	t1, 0x0(t0)
+	li	t2, 0x00000000
+	or	t3, t1, t2
+
+	li	t0, 0xb8000000		/* DDR_BASE_ADDRESS */
+	sw	t3, 0x1c(t0)		/* TAP_CONTROL_0_ADDRESS */
+	sw	t3, 0x20(t0)		/* TAP_CONTROL_1_ADDRESS */
+	sw	t3, 0x24(t0)		/* TAP_CONTROL_2_ADDRESS */
+	sw	t3, 0x28(t0)		/* TAP_CONTROL_3_ADDRESS */
+
+	li	t1, 0x00000010		/* Running the test 8 times */
+	sw	t1, 0x0068(t0)		/* PERF_COMP_ADDR_1_ADDRESS */
+
+	li	t1, 0xfa5de83f		/* 4 Row Address Bits, 4 Column Address Bits, 2 BA bits */
+	sw	t1, 0x002c(t0)		/* PERF_MASK_ADDR_0_ADDRESS */
+
+	li	t1, 0x0000ffff
+	sw	t1, 0x0070(t0)		/* PERF_COMP_AHB_GE0_1_ADDRESS */
+
+	li	t1, 0x0000ffff
+	sw	t1, 0x0040(t0)		/* PERF_COMP_AHB_GE1_0_ADDRESS */
+
+	li	t1, 0x0000ffff
+	sw	t1, 0x0078(t0)		/* PERF_COMP_AHB_GE1_1_ADDRESS */
+
+	li	t1, 0x0000ffff
+	sw	t1, 0x0034(t0)		/* PERF_MASK_AHB_GE0_0_ADDRESS */
+
+	li	t1, 0x0000ffff
+	sw	t1, 0x006c(t0)		/* PERF_MASK_AHB_GE0_1_ADDRESS */
+
+	li	t1, 0x0000ffff
+	sw	t1, 0x003c(t0)		/* PERF_MASK_AHB_GE1_0_ADDRESS */
+
+	li	t1, 0x0000ffff
+	sw	t1, 0x0074(t0)		/* PERF_MASK_AHB_GE1_1_ADDRESS */
+
+	li	t1, 0x0000ffff
+	sw	t1, 0x0038(t0)		/* PERF_COMP_AHB_GE0_0_ADDRESS */
+
+	li	t1, 0x00000001
+	sw	t1, 0x011c(t0)		/* DDR_BIST_ADDRESS */
+
+	li	t2, 0x1
+
+_bist_done_poll:
+	lw	t1, 0x0120(t0)		/* DDR_BIST_STATUS_ADDRESS */
+	and	t1, t1, t2
+	bne	t1, t2, _bist_done_poll
+	 nop
+
+	lw	t1, 0x0120(t0)		/* DDR_BIST_STATUS_ADDRESS */
+	li	t4, 0x000001fe
+	and	t2, t1, t4
+	srl	t2, t2, 0x1		/* no. of Pass Runs */
+
+	li	t5, 0x00000000
+	sw	t5, 0x011c(t0)		/* DDR_BIST_ADDRESS	- Stop the DDR BIST test */
+
+	li	t5, 0x0001fe00
+	and	t5, t5, t1
+	bnez	t5, _iterate_tap		/* This is a redundant compare but nevertheless - Comparing the FAILS */
+	 nop
+
+	lw	t1, 0x0068(t0)		/* PERF_COMP_ADDR_1_ADDRESS */
+	li	t3, 0x000001fe
+	and	t3, t3, t1
+	srl	t3, t3, 0x1		/* No. of runs in the config register. */
+	bne	t3, t2, _iterate_tap
+	 nop
+
+pass_tap:
+	li	t0, 0xbd001f00
+	lw	t1, 0x4(t0)
+	addiu	t1, t1, 0x1
+	sw	t1, 0x4(t0)
+
+	li	t0, 0xbd001f10
+	lw	t1, 0x0(t0)
+	li	t2, 0xaa55aa55
+	beq	t1, t2, _first_pass
+	 nop
+
+	li	t0, 0xbd001f00
+	lw	t1, 0x0(t0)
+	li	t0, 0xbd001f10
+	sw	t1, 0x4(t0)
+	 nop
+	b	_iterate_tap
+	 nop
+
+_first_pass:
+	li	t0, 0xbd001f00
+	lw	t1, 0x0(t0)
+	li	t0, 0xbd001f10
+	sw	t1, 0x0(t0)
+	sw	t1, 0x4(t0)
+	 nop
+
+_iterate_tap:
+	li	t0, 0xbd001f00
+	lw	t1, 0x0(t0)
+	li	t2, 0x3f
+	beq	t1, t2, _STOP_TEST
+	 nop
+
+	addiu	t1, t1, 0x1
+	sw	t1, 0x0(t0)
+	 nop
+	b	_CHANGE_TAPS
+	 nop
+
+_STOP_TEST:
+	li	t0, 0xbd001f00
+	lw	t1, 0x4(t0)
+	bnez	t1, _load_center_tap
+	 nop
+
+	li	t3, 0x8			/* Default Tap to be used */
+	b	_load_tap_into_reg
+	 nop
+
+_load_center_tap:
+	li	t0, 0xbd001f10
+	lw	t1, 0x0(t0)
+	lw	t2, 0x4(t0)
+	add	t3, t1, t2
+	srl	t3, t3, 0x1
+	li	t4, 0x3f
+	and	t3, t3, t4
+
+_load_tap_into_reg:
+	li	t0, 0xb8000000
+	sw	t3, 0x1c(t0)		/* TAP_CONTROL_0_ADDRESS */
+	sw	t3, 0x20(t0)		/* TAP_CONTROL_1_ADDRESS */
+	sw	t3, 0x24(t0)		/* TAP_CONTROL_2_ADDRESS */
+	sw	t3, 0x28(t0)		/* TAP_CONTROL_3_ADDRESS */
+
+	 nop
+	jr ra
+	 nop
+    END(ddr_tap_tuning)
diff --git a/arch/mips/mach-ath79/reset.c b/arch/mips/mach-ath79/reset.c
index 6a94d88..0ab3ab6 100644
--- a/arch/mips/mach-ath79/reset.c
+++ b/arch/mips/mach-ath79/reset.c
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (C) 2015-2016 Wills Wang <wills.wang@live.com>
+ * Copyright (C) 2018-2019 Rosy Song <rosysong@rosinson.com>
  */
 
 #include <common.h>
@@ -11,6 +12,44 @@
 #include <mach/ath79.h>
 #include <mach/ar71xx_regs.h>
 
+/* QCA956X ETH_SGMII_SERDES Registers */
+#define SGMII_SERDES_RES_CALIBRATION_LSB 23
+#define SGMII_SERDES_RES_CALIBRATION_MASK 0x07800000
+#define SGMII_SERDES_RES_CALIBRATION_SET(x) \
+	(((x) << SGMII_SERDES_RES_CALIBRATION_LSB) & SGMII_SERDES_RES_CALIBRATION_MASK)
+#define SGMII_SERDES_CDR_BW_LSB 1
+#define SGMII_SERDES_CDR_BW_MASK 0x00000006
+#define SGMII_SERDES_CDR_BW_SET(x) \
+	(((x) << SGMII_SERDES_CDR_BW_LSB) & SGMII_SERDES_CDR_BW_MASK)
+#define SGMII_SERDES_TX_DR_CTRL_LSB 4
+#define SGMII_SERDES_TX_DR_CTRL_MASK 0x00000070
+#define SGMII_SERDES_TX_DR_CTRL_SET(x) \
+	(((x) << SGMII_SERDES_TX_DR_CTRL_LSB) & SGMII_SERDES_TX_DR_CTRL_MASK)
+#define SGMII_SERDES_PLL_BW_LSB 8
+#define SGMII_SERDES_PLL_BW_MASK 0x00000100
+#define SGMII_SERDES_PLL_BW_SET(x) \
+	(((x) << SGMII_SERDES_PLL_BW_LSB) & SGMII_SERDES_PLL_BW_MASK)
+#define SGMII_SERDES_EN_SIGNAL_DETECT_LSB 16
+#define SGMII_SERDES_EN_SIGNAL_DETECT_MASK 0x00010000
+#define SGMII_SERDES_EN_SIGNAL_DETECT_SET(x) \
+	(((x) << SGMII_SERDES_EN_SIGNAL_DETECT_LSB) & SGMII_SERDES_EN_SIGNAL_DETECT_MASK)
+#define SGMII_SERDES_FIBER_SDO_LSB 17
+#define SGMII_SERDES_FIBER_SDO_MASK 0x00020000
+#define SGMII_SERDES_FIBER_SDO_SET(x) \
+	(((x) << SGMII_SERDES_FIBER_SDO_LSB) & SGMII_SERDES_FIBER_SDO_MASK)
+#define SGMII_SERDES_VCO_REG_LSB 27
+#define SGMII_SERDES_VCO_REG_MASK 0x78000000
+#define SGMII_SERDES_VCO_REG_SET(x) \
+	(((x) << SGMII_SERDES_VCO_REG_LSB) & SGMII_SERDES_VCO_REG_MASK)
+#define SGMII_SERDES_VCO_FAST_LSB 9
+#define SGMII_SERDES_VCO_FAST_MASK 0x00000200
+#define SGMII_SERDES_VCO_FAST_GET(x) \
+	(((x) & SGMII_SERDES_VCO_FAST_MASK) >> SGMII_SERDES_VCO_FAST_LSB)
+#define SGMII_SERDES_VCO_SLOW_LSB 10
+#define SGMII_SERDES_VCO_SLOW_MASK 0x00000400
+#define SGMII_SERDES_VCO_SLOW_GET(x) \
+	(((x) & SGMII_SERDES_VCO_SLOW_MASK) >> SGMII_SERDES_VCO_SLOW_LSB)
+
 void _machine_restart(void)
 {
 	void __iomem *base;
@@ -152,6 +191,236 @@
 	return 0;
 }
 
+static int qca956x_sgmii_cal(void)
+{
+	int i;
+	u32 reg, rev_sgmii_val;
+	u32 vco_fast, vco_slow;
+	u32 start_val = 0, end_val = 0;
+	void __iomem *gregs = map_physmem(AR71XX_MII_BASE, AR71XX_MII_SIZE,
+					  MAP_NOCACHE);
+	void __iomem *pregs = map_physmem(AR71XX_PLL_BASE, AR71XX_PLL_SIZE,
+					  MAP_NOCACHE);
+	void __iomem *rregs = map_physmem(AR71XX_RESET_BASE, AR71XX_RESET_SIZE,
+					  MAP_NOCACHE);
+	const u32 mask = QCA956X_RESET_SGMII_ASSERT | QCA956X_RESET_SGMII;
+
+	writel(BIT(2) | BIT(0), pregs + QCA956X_PLL_ETH_SGMII_SERDES_REG);
+
+	reg = readl(gregs + QCA956X_GMAC_REG_SGMII_SERDES);
+	vco_fast = SGMII_SERDES_VCO_FAST_GET(reg);
+	vco_slow = SGMII_SERDES_VCO_SLOW_GET(reg);
+
+	/* Set resistor calibration from 0000 to 1111 */
+	for (i = 0; i < 0x10; i++) {
+		reg = (readl(gregs + QCA956X_GMAC_REG_SGMII_SERDES) &
+		      ~SGMII_SERDES_RES_CALIBRATION_MASK) |
+		      SGMII_SERDES_RES_CALIBRATION_SET(i);
+		writel(reg, gregs + QCA956X_GMAC_REG_SGMII_SERDES);
+
+		udelay(50);
+
+		reg = readl(gregs + QCA956X_GMAC_REG_SGMII_SERDES);
+		if (vco_fast != SGMII_SERDES_VCO_FAST_GET(reg) ||
+		    vco_slow != SGMII_SERDES_VCO_SLOW_GET(reg)) {
+			if (start_val == 0) {
+				start_val = i;
+				end_val = i;
+			} else {
+				end_val = i;
+			}
+		}
+		vco_fast = SGMII_SERDES_VCO_FAST_GET(reg);
+		vco_slow = SGMII_SERDES_VCO_SLOW_GET(reg);
+	}
+
+	if (start_val == 0)
+		rev_sgmii_val = 0x7;
+	else
+		rev_sgmii_val = (start_val + end_val) >> 1;
+
+	writel((readl(gregs + QCA956X_GMAC_REG_SGMII_SERDES) &
+	       ~SGMII_SERDES_RES_CALIBRATION_MASK) |
+	       SGMII_SERDES_RES_CALIBRATION_SET(rev_sgmii_val),
+	       gregs + QCA956X_GMAC_REG_SGMII_SERDES);
+
+	writel(BIT(2) | BIT(0), pregs + QCA956X_PLL_ETH_SGMII_SERDES_REG);
+
+	reg = readl(gregs + QCA956X_GMAC_REG_SGMII_SERDES);
+	writel(SGMII_SERDES_CDR_BW_SET(3) | SGMII_SERDES_TX_DR_CTRL_SET(1) |
+	       SGMII_SERDES_PLL_BW_SET(1) | SGMII_SERDES_EN_SIGNAL_DETECT_SET(1) |
+	       SGMII_SERDES_FIBER_SDO_SET(1) | SGMII_SERDES_VCO_REG_SET(3) | reg,
+	       gregs + QCA956X_GMAC_REG_SGMII_SERDES);
+
+	setbits_be32(rregs + QCA956X_RESET_REG_RESET_MODULE, mask);
+	mdelay(1);
+	clrbits_be32(rregs + QCA956X_RESET_REG_RESET_MODULE, mask);
+	mdelay(1);
+
+	while (!(readl(gregs + QCA956X_GMAC_REG_SGMII_SERDES) & BIT(15)))
+		/* NOP */;
+
+	return 0;
+}
+
+static int qca956x_sgmii_setup(void)
+{
+	int i;
+	u32 s = 0, reg = 0;
+	u32 _regs[] = {
+		BIT(4),	/* HW_RX_125M_N */
+		BIT(2),	/* RX_125M_N */
+		BIT(3),	/* TX_125M_N */
+		BIT(0),	/* RX_CLK_N */
+		BIT(1),	/* TX_CLK_N */
+	};
+	void __iomem *gregs = map_physmem(AR71XX_MII_BASE, AR71XX_MII_SIZE,
+					  MAP_NOCACHE);
+
+	/* Force sgmii mode */
+	writel(BIT(6) | BIT(15) | BIT(8), gregs + QCA956X_GMAC_REG_MR_AN_CTRL);
+	udelay(10);
+	writel(0x2 | BIT(5) | (0x2 << 6), gregs + QCA956X_GMAC_REG_SGMII_CONFIG);
+
+	/* SGMII reset sequence sugguest by qca systems team. */
+	writel(0, gregs + QCA956X_GMAC_REG_SGMII_RESET);
+	for (i = 0; i < ARRAY_SIZE(_regs); i++) {
+		reg |= _regs[i];
+		writel(reg, gregs + QCA956X_GMAC_REG_SGMII_RESET);
+	}
+
+	writel(readl(gregs + QCA956X_GMAC_REG_MR_AN_CTRL) & ~BIT(15),
+	       gregs + QCA956X_GMAC_REG_MR_AN_CTRL);
+
+	/*
+	 * WARNING: Across resets SGMII link status goes to weird state.
+	 * if 0xb8070058 (SGMII_DEBUG Register) reads other than 0xf or 0x10
+	 * for sure we are in bad state.
+	 * Issue a PHY RESET in MR_AN_CONTROL_ADDRESS to keep going.
+	 */
+	i = 0;
+	s = (readl(gregs + QCA956X_GMAC_REG_SGMII_DEBUG) & 0xff);
+	while (!(s == 0xf || s == 0x10)) {
+		writel(readl(gregs + QCA956X_GMAC_REG_MR_AN_CTRL) | BIT(15),
+		       gregs + QCA956X_GMAC_REG_MR_AN_CTRL);
+		udelay(100);
+		writel(readl(gregs + QCA956X_GMAC_REG_MR_AN_CTRL) & ~BIT(15),
+		       gregs + QCA956X_GMAC_REG_MR_AN_CTRL);
+		if (i++ == 10)
+			break;
+		s = (readl(gregs + QCA956X_GMAC_REG_SGMII_DEBUG) & 0xff);
+	}
+
+	return 0;
+}
+
+static int qca956x_s17_reset(void)
+{
+	void __iomem *regs = map_physmem(AR71XX_GPIO_BASE, AR71XX_GPIO_SIZE,
+					  MAP_NOCACHE);
+	void __iomem *rregs = map_physmem(AR71XX_RESET_BASE, AR71XX_RESET_SIZE,
+					  MAP_NOCACHE);
+	const u32 mask = QCA956X_RESET_SGMII_ASSERT | QCA956X_RESET_SGMII |
+			 QCA956X_RESET_EXTERNAL | QCA956X_RESET_SGMII_ANALOG |
+			 QCA956X_RESET_SWITCH;
+	/* Bits(Reserved in datasheet) should be set to 1 */
+	const u32 mask_r = QCA956X_RESET_SGMII_ASSERT | QCA956X_RESET_SGMII |
+			 QCA956X_RESET_EXTERNAL;
+
+	setbits_be32(rregs + QCA956X_RESET_REG_RESET_MODULE, mask);
+	mdelay(1);
+	clrbits_be32(rregs + QCA956X_RESET_REG_RESET_MODULE, mask_r);
+	mdelay(1);
+
+	/* Reset s17 switch(GPIO11) SYS_RST_L */
+	writel(readl(regs + AR71XX_GPIO_REG_OE) & ~BIT(11),
+	       regs + AR71XX_GPIO_REG_OE);
+	udelay(100);
+
+	writel(readl(regs + AR71XX_GPIO_REG_OUT) & ~BIT(11),
+	       regs + AR71XX_GPIO_REG_OUT);
+	udelay(100);
+	writel(readl(regs + AR71XX_GPIO_REG_OUT) | BIT(11),
+	       regs + AR71XX_GPIO_REG_OUT);
+
+	return 0;
+}
+
+static int qca956x_init_mdio(void)
+{
+	u32 reg;
+	void __iomem *regs = map_physmem(AR71XX_GPIO_BASE, AR71XX_GPIO_SIZE,
+						MAP_NOCACHE);
+	void __iomem *rregs = map_physmem(AR71XX_RESET_BASE, AR71XX_RESET_SIZE,
+					  MAP_NOCACHE);
+	const u32 mask = QCA956X_RESET_GE0_MDIO | QCA956X_RESET_GE0_MAC |
+			 QCA956X_RESET_GE1_MDIO | QCA956X_RESET_GE1_MAC;
+
+	setbits_be32(rregs + QCA956X_RESET_REG_RESET_MODULE, mask);
+	mdelay(1);
+	clrbits_be32(rregs + QCA956X_RESET_REG_RESET_MODULE, mask);
+	mdelay(1);
+
+	/* GPIO4 as MDI */
+	reg = readl(regs + QCA956X_GPIO_REG_IN_ENABLE3);
+	reg &= ~(0xff << 16);
+	reg |= (0x4 << 16);
+	writel(reg, regs + QCA956X_GPIO_REG_IN_ENABLE3);
+
+	/* GPIO4 as MDO */
+	reg = readl(regs + QCA956X_GPIO_REG_OUT_FUNC1);
+	reg &= ~0xff;
+	reg |= 0x20;
+	writel(reg, regs + QCA956X_GPIO_REG_OUT_FUNC1);
+
+	/* Init MDC(GPIO3) / MDIO(GPIO4) */
+	reg = readl(regs + AR71XX_GPIO_REG_OE);
+	reg &= ~BIT(4);
+	writel(reg, regs + AR71XX_GPIO_REG_OE);
+	udelay(100);
+
+	reg = readl(regs + AR71XX_GPIO_REG_OE);
+	reg &= ~BIT(3);
+	writel(reg, regs + AR71XX_GPIO_REG_OE);
+	udelay(100);
+
+	/* GPIO3 as MDI */
+	reg = readl(regs + QCA956X_GPIO_REG_OUT_FUNC0);
+	reg &= ~(0xff << 24);
+	reg |= (0x21 << 24);
+	writel(reg, regs + QCA956X_GPIO_REG_OUT_FUNC0);
+
+	return 0;
+}
+
+static int eth_init_qca956x(void)
+{
+	void __iomem *pregs = map_physmem(AR71XX_PLL_BASE, AR71XX_PLL_SIZE,
+					  MAP_NOCACHE);
+	void __iomem *gregs = map_physmem(AR71XX_MII_BASE, AR71XX_MII_SIZE,
+					  MAP_NOCACHE);
+
+	qca956x_sgmii_cal();
+	qca956x_s17_reset();
+	qca956x_init_mdio();
+
+	if (ath79_get_bootstrap() & QCA956X_BOOTSTRAP_REF_CLK_40)
+		writel(0x45500, pregs + QCA956X_PLL_SWITCH_CLK_CTRL_REG);
+	else
+		writel(0xc5200, pregs + QCA956X_PLL_SWITCH_CLK_CTRL_REG);
+
+	qca956x_sgmii_setup();
+
+	writel((3 << 16) | (3 << 14) | (1 << 0) | (1 << 6),
+	       gregs + QCA956X_GMAC_REG_ETH_CFG);
+
+	writel((1 << 31) | (2 << 28) | (2 << 26) | (1 << 25),
+	       pregs + QCA956X_PLL_ETH_XMII_CTRL_REG);
+	mdelay(1);
+
+	return 0;
+}
+
 int ath79_eth_reset(void)
 {
 	/*
@@ -164,6 +433,8 @@
 		return eth_init_ar934x();
 	if (soc_is_qca953x())
 		return eth_init_qca953x();
+	if (soc_is_qca956x())
+		return eth_init_qca956x();
 
 	return -EINVAL;
 }
diff --git a/arch/mips/mach-mscc/include/mach/servalt/servalt_devcpu_gcb.h b/arch/mips/mach-mscc/include/mach/servalt/servalt_devcpu_gcb.h
index f6e7245..493eaad 100644
--- a/arch/mips/mach-mscc/include/mach/servalt/servalt_devcpu_gcb.h
+++ b/arch/mips/mach-mscc/include/mach/servalt/servalt_devcpu_gcb.h
@@ -17,4 +17,6 @@
 #define GPIO_GPIO_ALT(x)                                  (0x74 + 4 * (x))
 #define GPIO_GPIO_ALT1(x)                                 (0x7c + 4 * (x))
 
+#define GCB_PHY_CFG                                       0x118
+
 #endif
diff --git a/arch/mips/mach-mt7620/Kconfig b/arch/mips/mach-mt7620/Kconfig
index 4ebcb4b..a983443 100644
--- a/arch/mips/mach-mt7620/Kconfig
+++ b/arch/mips/mach-mt7620/Kconfig
@@ -22,12 +22,12 @@
 	prompt "Board select"
 
 config BOARD_GARDENA_SMART_GATEWAY_MT7688
-	bool "Gardena Smart Gateway"
+	bool "GARDENA smart Gateway"
 	depends on SOC_MT7620
 	select BOARD_LATE_INIT
 	select SUPPORTS_BOOT_RAM
 	help
-	  Gardena Smart Gateway boards have a MT7688 SoC with 128 MiB of RAM
+	  GARDENA smart Gateway boards have a MT7688 SoC with 128 MiB of RAM
 	  and 8 MiB of flash (SPI NOR) and additional SPI NAND storage.
 
 config BOARD_LINKIT_SMART_7688
diff --git a/arch/nds32/dts/ae3xx.dts b/arch/nds32/dts/ae3xx.dts
index 272eb33..7bba2a2 100644
--- a/arch/nds32/dts/ae3xx.dts
+++ b/arch/nds32/dts/ae3xx.dts
@@ -93,7 +93,7 @@
 		clocks = <&spiclk>;
 		interrupts = <3 4>;
 			flash@0 {
-			compatible = "spi-flash";
+			compatible = "jedec,spi-nor";
 			spi-max-frequency = <50000000>;
 			reg = <0>;
 			spi-cpol;
diff --git a/arch/riscv/dts/ae350_32.dts b/arch/riscv/dts/ae350_32.dts
index 2ec01a5..cb6ee13 100644
--- a/arch/riscv/dts/ae350_32.dts
+++ b/arch/riscv/dts/ae350_32.dts
@@ -256,7 +256,7 @@
 		interrupts = <4 4>;
 		interrupt-parent = <&plic0>;
 		flash@0 {
-			compatible = "spi-flash";
+			compatible = "jedec,spi-nor";
 			spi-max-frequency = <50000000>;
 			reg = <0>;
 			spi-cpol;
diff --git a/arch/riscv/dts/ae350_64.dts b/arch/riscv/dts/ae350_64.dts
index cde5cde..705491a 100644
--- a/arch/riscv/dts/ae350_64.dts
+++ b/arch/riscv/dts/ae350_64.dts
@@ -256,7 +256,7 @@
 		interrupts = <4 4>;
 		interrupt-parent = <&plic0>;
 		flash@0 {
-			compatible = "spi-flash";
+			compatible = "jedec,spi-nor";
 			spi-max-frequency = <50000000>;
 			reg = <0>;
 			spi-cpol;
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 87d8e5b..8b2d645 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -493,6 +493,7 @@
 			compatible = "denx,u-boot-probe-test";
 			first-syscon = <&syscon0>;
 			second-sys-ctrl = <&another_system_controller>;
+			third-syscon = <&syscon2>;
 		};
 	};
 
@@ -578,7 +579,7 @@
 		cs-gpios = <0>, <&gpio_a 0>;
 		spi.bin@0 {
 			reg = <0>;
-			compatible = "spansion,m25p16", "spi-flash";
+			compatible = "spansion,m25p16", "jedec,spi-nor";
 			spi-max-frequency = <40000000>;
 			sandbox,filename = "spi.bin";
 		};
@@ -597,7 +598,7 @@
 			0x38 8>;
 	};
 
-	syscon@2 {
+	syscon2: syscon@2 {
 		compatible = "simple-mfd", "syscon";
 		reg = <0x40 5
 			0x48 6
diff --git a/arch/sandbox/include/asm/sdl.h b/arch/sandbox/include/asm/sdl.h
index 1027b59..c45dbdd 100644
--- a/arch/sandbox/include/asm/sdl.h
+++ b/arch/sandbox/include/asm/sdl.h
@@ -104,7 +104,7 @@
 	return -ENODEV;
 }
 
-int sandbox_sdl_sound_play(const void *data, uint count)
+static inline int sandbox_sdl_sound_play(const void *data, uint count)
 {
 	return -ENODEV;
 }
@@ -114,7 +114,7 @@
 	return -ENODEV;
 }
 
-int sandbox_sdl_sound_init(int rate, int channels)
+static inline int sandbox_sdl_sound_init(int rate, int channels)
 {
 	return -ENODEV;
 }
diff --git a/arch/sandbox/include/asm/types.h b/arch/sandbox/include/asm/types.h
index 7cd56b4..c1a5d2a 100644
--- a/arch/sandbox/include/asm/types.h
+++ b/arch/sandbox/include/asm/types.h
@@ -18,21 +18,21 @@
 /*
  * Number of bits in a C 'long' on this architecture.
  */
-#ifdef	CONFIG_PHYS64
+#ifdef	CONFIG_PHYS_64BIT
 #define BITS_PER_LONG 64
-#else	/* CONFIG_PHYS64 */
+#else	/* CONFIG_PHYS_64BIT */
 #define BITS_PER_LONG 32
-#endif	/* CONFIG_PHYS64 */
+#endif	/* CONFIG_PHYS_64BIT */
 
-#ifdef	CONFIG_PHYS64
+#ifdef	CONFIG_PHYS_64BIT
 typedef unsigned long long dma_addr_t;
 typedef u64 phys_addr_t;
 typedef u64 phys_size_t;
-#else	/* CONFIG_PHYS64 */
+#else	/* CONFIG_PHYS_64BIT */
 typedef unsigned long dma_addr_t;
 typedef u32 phys_addr_t;
 typedef u32 phys_size_t;
-#endif	/* CONFIG_PHYS64 */
+#endif	/* CONFIG_PHYS_64BIT */
 
 #endif /* __KERNEL__ */
 
diff --git a/arch/sandbox/lib/pci_io.c b/arch/sandbox/lib/pci_io.c
index 5039973..01822c6 100644
--- a/arch/sandbox/lib/pci_io.c
+++ b/arch/sandbox/lib/pci_io.c
@@ -34,7 +34,7 @@
 		return 0;
 	}
 
-	debug("%s: failed: addr=%x\n", __func__, paddr);
+	debug("%s: failed: addr=%pap\n", __func__, &paddr);
 	return -ENOSYS;
 }
 
diff --git a/arch/x86/dts/bayleybay.dts b/arch/x86/dts/bayleybay.dts
index 291dc07..d0168e8 100644
--- a/arch/x86/dts/bayleybay.dts
+++ b/arch/x86/dts/bayleybay.dts
@@ -175,7 +175,7 @@
 					#size-cells = <1>;
 					reg = <0>;
 					compatible = "winbond,w25q64dw",
-						"spi-flash";
+						"jedec,spi-nor";
 					memory-map = <0xff800000 0x00800000>;
 					rw-mrc-cache {
 						label = "rw-mrc-cache";
diff --git a/arch/x86/dts/baytrail_som-db5800-som-6867.dts b/arch/x86/dts/baytrail_som-db5800-som-6867.dts
index 4e8a761..5abbc66 100644
--- a/arch/x86/dts/baytrail_som-db5800-som-6867.dts
+++ b/arch/x86/dts/baytrail_som-db5800-som-6867.dts
@@ -199,7 +199,7 @@
 					#size-cells = <1>;
 					reg = <0>;
 					compatible = "macronix,mx25l6405d",
-						"spi-flash";
+						"jedec,spi-nor";
 					memory-map = <0xff800000 0x00800000>;
 					rw-mrc-cache {
 						label = "rw-mrc-cache";
diff --git a/arch/x86/dts/cherryhill.dts b/arch/x86/dts/cherryhill.dts
index 39e2d2f..37146fd 100644
--- a/arch/x86/dts/cherryhill.dts
+++ b/arch/x86/dts/cherryhill.dts
@@ -147,7 +147,7 @@
 					#address-cells = <1>;
 					#size-cells = <1>;
 					reg = <0>;
-					compatible = "macronix,mx25u6435f", "spi-flash";
+					compatible = "macronix,mx25u6435f", "jedec,spi-nor";
 					memory-map = <0xff800000 0x00800000>;
 					rw-mrc-cache {
 						label = "rw-mrc-cache";
diff --git a/arch/x86/dts/chromebook_link.dts b/arch/x86/dts/chromebook_link.dts
index c5653fe..09488f1 100644
--- a/arch/x86/dts/chromebook_link.dts
+++ b/arch/x86/dts/chromebook_link.dts
@@ -429,7 +429,7 @@
 					u-boot,dm-pre-reloc;
 					reg = <0>;
 					compatible = "winbond,w25q64",
-							"spi-flash";
+							"jedec,spi-nor";
 					memory-map = <0xff800000 0x00800000>;
 					rw-mrc-cache {
 						label = "rw-mrc-cache";
diff --git a/arch/x86/dts/chromebook_samus.dts b/arch/x86/dts/chromebook_samus.dts
index ad687ce..35211ed 100644
--- a/arch/x86/dts/chromebook_samus.dts
+++ b/arch/x86/dts/chromebook_samus.dts
@@ -567,7 +567,7 @@
 					#address-cells = <1>;
 					reg = <0>;
 					compatible = "winbond,w25q64",
-							"spi-flash";
+							"jedec,spi-nor";
 					memory-map = <0xff800000 0x00800000>;
 					rw-mrc-cache {
 						label = "rw-mrc-cache";
diff --git a/arch/x86/dts/chromebox_panther.dts b/arch/x86/dts/chromebox_panther.dts
index f56e482..bcd4c4d 100644
--- a/arch/x86/dts/chromebox_panther.dts
+++ b/arch/x86/dts/chromebox_panther.dts
@@ -47,7 +47,7 @@
 					#address-cells = <1>;
 					reg = <0>;
 					compatible = "winbond,w25q64",
-						"spi-flash";
+						"jedec,spi-nor";
 					memory-map = <0xff800000 0x00800000>;
 					rw-mrc-cache {
 						label = "rw-mrc-cache";
diff --git a/arch/x86/dts/conga-qeval20-qa3-e3845.dts b/arch/x86/dts/conga-qeval20-qa3-e3845.dts
index 5884dbc..70b8c04 100644
--- a/arch/x86/dts/conga-qeval20-qa3-e3845.dts
+++ b/arch/x86/dts/conga-qeval20-qa3-e3845.dts
@@ -186,7 +186,7 @@
 					#size-cells = <1>;
 					reg = <0>;
 					compatible = "stmicro,n25q064a",
-						"spi-flash";
+						"jedec,spi-nor";
 					memory-map = <0xff800000 0x00800000>;
 					rw-mrc-cache {
 						label = "rw-mrc-cache";
diff --git a/arch/x86/dts/cougarcanyon2.dts b/arch/x86/dts/cougarcanyon2.dts
index 9801790..c6ba811 100644
--- a/arch/x86/dts/cougarcanyon2.dts
+++ b/arch/x86/dts/cougarcanyon2.dts
@@ -154,7 +154,7 @@
 
 				spi-flash@0 {
 					reg = <0>;
-					compatible = "winbond,w25q64bv", "spi-flash";
+					compatible = "winbond,w25q64bv", "jedec,spi-nor";
 					memory-map = <0xff800000 0x00800000>;
 				};
 			};
diff --git a/arch/x86/dts/crownbay.dts b/arch/x86/dts/crownbay.dts
index 8938a94..f492c35 100644
--- a/arch/x86/dts/crownbay.dts
+++ b/arch/x86/dts/crownbay.dts
@@ -224,7 +224,7 @@
 				spi-flash@0 {
 					reg = <0>;
 					compatible = "sst,25vf016b",
-						"spi-flash";
+						"jedec,spi-nor";
 					memory-map = <0xffe00000 0x00200000>;
 				};
 			};
diff --git a/arch/x86/dts/dfi-bt700.dtsi b/arch/x86/dts/dfi-bt700.dtsi
index 51d33e7..e9930cb 100644
--- a/arch/x86/dts/dfi-bt700.dtsi
+++ b/arch/x86/dts/dfi-bt700.dtsi
@@ -197,7 +197,7 @@
 					#size-cells = <1>;
 					reg = <0>;
 					compatible = "stmicro,n25q064a",
-						"spi-flash";
+						"jedec,spi-nor";
 					memory-map = <0xff800000 0x00800000>;
 					rw-mrc-cache {
 						label = "rw-mrc-cache";
diff --git a/arch/x86/dts/galileo.dts b/arch/x86/dts/galileo.dts
index 3a5d168..5de4568 100644
--- a/arch/x86/dts/galileo.dts
+++ b/arch/x86/dts/galileo.dts
@@ -139,7 +139,7 @@
 					#address-cells = <1>;
 					reg = <0>;
 					compatible = "winbond,w25q64",
-						"spi-flash";
+						"jedec,spi-nor";
 					memory-map = <0xff800000 0x00800000>;
 					rw-mrc-cache {
 						label = "rw-mrc-cache";
diff --git a/arch/x86/dts/minnowmax.dts b/arch/x86/dts/minnowmax.dts
index 6c65fb9..f4cdb2c 100644
--- a/arch/x86/dts/minnowmax.dts
+++ b/arch/x86/dts/minnowmax.dts
@@ -199,7 +199,7 @@
 					#size-cells = <1>;
 					reg = <0>;
 					compatible = "stmicro,n25q064a",
-						"spi-flash";
+						"jedec,spi-nor";
 					memory-map = <0xff800000 0x00800000>;
 					rw-mrc-cache {
 						label = "rw-mrc-cache";
diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c b/board/CZ.NIC/turris_omnia/turris_omnia.c
index c7f6479..c21d2f3 100644
--- a/board/CZ.NIC/turris_omnia/turris_omnia.c
+++ b/board/CZ.NIC/turris_omnia/turris_omnia.c
@@ -379,7 +379,7 @@
 		puts("Cannot find Armada 385 watchdog!\n");
 	} else {
 		puts("Enabling Armada 385 watchdog.\n");
-		wdt_start(watchdog_dev, (u32) 25000000 * 120, 0);
+		wdt_start(watchdog_dev, 120000, 0);
 	}
 # endif
 
diff --git a/board/Marvell/db-xc3-24g4xg/.gitignore b/board/Marvell/db-xc3-24g4xg/.gitignore
new file mode 100644
index 0000000..775b934
--- /dev/null
+++ b/board/Marvell/db-xc3-24g4xg/.gitignore
@@ -0,0 +1 @@
+kwbimage.cfg
diff --git a/board/Marvell/db-xc3-24g4xg/MAINTAINERS b/board/Marvell/db-xc3-24g4xg/MAINTAINERS
new file mode 100644
index 0000000..2b27e48
--- /dev/null
+++ b/board/Marvell/db-xc3-24g4xg/MAINTAINERS
@@ -0,0 +1,7 @@
+DB-XC3-24G4XG BOARD
+M:	Chris Packham <chris.packham@alliedtelesis.co.nz>
+S:	Maintained
+F:	board/Marvell/db-xc3-24g4xg/
+F:	include/configs/db-xc3-24g4xg.h
+F:	configs/db-xc3-24g4xg_defconfig
+F:	arch/arm/dts/armada-xp-db-xc3-24g4xg.dts
diff --git a/board/Marvell/db-xc3-24g4xg/Makefile b/board/Marvell/db-xc3-24g4xg/Makefile
new file mode 100644
index 0000000..4dd5790
--- /dev/null
+++ b/board/Marvell/db-xc3-24g4xg/Makefile
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2015 Stefan Roese <sr@denx.de>
+
+obj-y	:= db-xc3-24g4xg.o
+extra-y	:= kwbimage.cfg
+
+quiet_cmd_sed = SED     $@
+      cmd_sed = sed $(SEDFLAGS_$(@F)) $< >$(dir $<)$(@F)
+
+SEDFLAGS_kwbimage.cfg =-e "s|^BINARY.*|BINARY $(srctree)/$(@D)/binary.0 0000005b 00000068|"
+$(src)/kwbimage.cfg: $(src)/kwbimage.cfg.in include/autoconf.mk \
+		include/config/auto.conf
+	  $(call if_changed,sed)
diff --git a/board/Marvell/db-xc3-24g4xg/README b/board/Marvell/db-xc3-24g4xg/README
new file mode 100644
index 0000000..5e479b4
--- /dev/null
+++ b/board/Marvell/db-xc3-24g4xg/README
@@ -0,0 +1,4 @@
+To generate binary.0 from Marvell's bin_hdr.elf use the following command
+
+    arm-softfloat-linux-gnueabi-objcopy -S -O binary bin_hdr.elf \
+       board/Marvell/db-xc3-24g4xg/binary.0
diff --git a/board/Marvell/db-xc3-24g4xg/binary.0 b/board/Marvell/db-xc3-24g4xg/binary.0
new file mode 100644
index 0000000..8dd6872
--- /dev/null
+++ b/board/Marvell/db-xc3-24g4xg/binary.0
@@ -0,0 +1,11 @@
+--------
+WARNING:
+--------
+This file should contain the bin_hdr generated by the original Marvell
+U-Boot implementation. As this is currently not included in this
+U-Boot version, we have added this placeholder, so that the U-Boot
+image can be generated without errors.
+
+If you have a known to be working bin_hdr for your board, then you
+just need to replace this text file here with the binary header
+and recompile U-Boot.
diff --git a/board/Marvell/db-xc3-24g4xg/db-xc3-24g4xg.c b/board/Marvell/db-xc3-24g4xg/db-xc3-24g4xg.c
new file mode 100644
index 0000000..cae428f
--- /dev/null
+++ b/board/Marvell/db-xc3-24g4xg/db-xc3-24g4xg.c
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2015 Stefan Roese <sr@denx.de>
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <asm/gpio.h>
+#include <linux/mbus.h>
+#include <linux/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * These values and defines are taken from the Marvell U-Boot version
+ * "u-boot-2013.01-2016_T1.0.eng_drop_v6"
+ */
+#define DB_DX_AC3_GPP_OUT_ENA_LOW	(~(BIT(0) | BIT(2) | BIT(3) | BIT(4) | BIT(6) | BIT(12) \
+					| BIT(13) | BIT(16) | BIT(17) | BIT(20) | BIT(29)  | BIT(30)))
+#define DB_DX_AC3_GPP_OUT_ENA_MID	(~(0))
+#define DB_DX_AC3_GPP_OUT_VAL_LOW	(BIT(0) | BIT(2) | BIT(3) | BIT(4) | BIT(6) | BIT(12) \
+					| BIT(13) | BIT(16) | BIT(17) | BIT(20) | BIT(29)  | BIT(30))
+#define DB_DX_AC3_GPP_OUT_VAL_MID	0x0
+#define DB_DX_AC3_GPP_POL_LOW		0x0
+#define DB_DX_AC3_GPP_POL_MID		0x0
+
+int board_early_init_f(void)
+{
+	/* Configure MPP */
+	writel(0x00142222, MVEBU_MPP_BASE + 0x00);
+	writel(0x11122000, MVEBU_MPP_BASE + 0x04);
+	writel(0x44444004, MVEBU_MPP_BASE + 0x08);
+	writel(0x14444444, MVEBU_MPP_BASE + 0x0c);
+	writel(0x00000001, MVEBU_MPP_BASE + 0x10);
+
+	/* Set GPP Out value */
+	writel(DB_DX_AC3_GPP_OUT_VAL_LOW, MVEBU_GPIO0_BASE + 0x00);
+	writel(DB_DX_AC3_GPP_OUT_VAL_MID, MVEBU_GPIO1_BASE + 0x00);
+
+	/* Set GPP Polarity */
+	writel(DB_DX_AC3_GPP_POL_LOW, MVEBU_GPIO0_BASE + 0x0c);
+	writel(DB_DX_AC3_GPP_POL_MID, MVEBU_GPIO1_BASE + 0x0c);
+
+	/* Set GPP Out Enable */
+	writel(DB_DX_AC3_GPP_OUT_ENA_LOW, MVEBU_GPIO0_BASE + 0x04);
+	writel(DB_DX_AC3_GPP_OUT_ENA_MID, MVEBU_GPIO1_BASE + 0x04);
+
+	return 0;
+}
+
+int board_init(void)
+{
+	/* address of boot parameters */
+	gd->bd->bi_boot_params = mvebu_sdram_bar(0) + 0x100;
+
+	return 0;
+}
+
+#ifdef CONFIG_DISPLAY_BOARDINFO
+int checkboard(void)
+{
+	puts("Board: " CONFIG_SYS_BOARD "\n");
+
+	return 0;
+}
+#endif
diff --git a/board/Marvell/db-xc3-24g4xg/kwbimage.cfg.in b/board/Marvell/db-xc3-24g4xg/kwbimage.cfg.in
new file mode 100644
index 0000000..b8bb7a6
--- /dev/null
+++ b/board/Marvell/db-xc3-24g4xg/kwbimage.cfg.in
@@ -0,0 +1,12 @@
+#
+# Copyright (C) 2014 Stefan Roese <sr@denx.de>
+#
+
+# Armada XP uses version 1 image format
+VERSION		1
+
+# Boot Media configurations
+BOOT_FROM	spi
+
+# Binary Header (bin_hdr) with DDR3 training code
+BINARY board/Marvell/db-xc3-24g4xg/binary.0 0000005b 00000068
diff --git a/board/Synology/ds414/ds414.c b/board/Synology/ds414/ds414.c
index eb3694e..d23e97c 100644
--- a/board/Synology/ds414/ds414.c
+++ b/board/Synology/ds414/ds414.c
@@ -115,14 +115,14 @@
 	return &ds414_ddr_modes[0];
 }
 
-MV_BIN_SERDES_CFG *board_serdes_cfg_get(u8 pex_mode)
+MV_BIN_SERDES_CFG *board_serdes_cfg_get(void)
 {
 	return &ds414_serdes_cfg[0];
 }
 
 u8 board_sat_r_get(u8 dev_num, u8 reg)
 {
-	return (0x1 << 1 | 1);
+	return 0xf;	/* All PEX ports support PCIe Gen2 */
 }
 
 int board_early_init_f(void)
diff --git a/board/alliedtelesis/x530/x530.c b/board/alliedtelesis/x530/x530.c
index d7d1942..6934fd8 100644
--- a/board/alliedtelesis/x530/x530.c
+++ b/board/alliedtelesis/x530/x530.c
@@ -7,6 +7,7 @@
 #include <command.h>
 #include <dm.h>
 #include <i2c.h>
+#include <wdt.h>
 #include <asm/gpio.h>
 #include <linux/mbus.h>
 #include <linux/io.h>
@@ -24,6 +25,10 @@
 #define CONFIG_NVS_LOCATION		0xf4800000
 #define CONFIG_NVS_SIZE			(512 << 10)
 
+#ifdef CONFIG_WATCHDOG
+static struct udevice *watchdog_dev;
+#endif
+
 static struct serdes_map board_serdes_map[] = {
 	{PEX0, SERDES_SPEED_5_GBPS, PEX_ROOT_COMPLEX_X1, 0, 0},
 	{DEFAULT_SERDES, SERDES_SPEED_5_GBPS, SERDES_DEFAULT_MODE, 0, 0},
@@ -75,6 +80,10 @@
 
 int board_early_init_f(void)
 {
+#ifdef CONFIG_WATCHDOG
+	watchdog_dev = NULL;
+#endif
+
 	/* Configure MPP */
 	writel(0x00001111, MVEBU_MPP_BASE + 0x00);
 	writel(0x00000000, MVEBU_MPP_BASE + 0x04);
@@ -88,6 +97,17 @@
 	return 0;
 }
 
+void spl_board_init(void)
+{
+#ifdef CONFIG_WATCHDOG
+	int ret;
+
+	ret = uclass_get_device(UCLASS_WDT, 0, &watchdog_dev);
+	if (!ret)
+		wdt_start(watchdog_dev, 120000, 0);
+#endif
+}
+
 int board_init(void)
 {
 	/* address of boot parameters */
@@ -100,8 +120,36 @@
 	/* DEV_READYn is not needed for NVS, ignore it when accessing CS1 */
 	writel(0x00004001, MVEBU_DEV_BUS_BASE + 0xc8);
 
+	spl_board_init();
+
 	return 0;
 }
+
+void arch_preboot_os(void)
+{
+#ifdef CONFIG_WATCHDOG
+	wdt_stop(watchdog_dev);
+#endif
+}
+
+#ifdef CONFIG_WATCHDOG
+void watchdog_reset(void)
+{
+	static ulong next_reset = 0;
+	ulong now;
+
+	if (!watchdog_dev)
+		return;
+
+	now = timer_get_us();
+
+	/* Do not reset the watchdog too often */
+	if (now > next_reset) {
+		wdt_reset(watchdog_dev);
+		next_reset = now + 1000;
+	}
+}
+#endif
 
 static int led_7seg_init(unsigned int segments)
 {
diff --git a/board/maxbcm/maxbcm.c b/board/maxbcm/maxbcm.c
index e8f8f7b..395904f 100644
--- a/board/maxbcm/maxbcm.c
+++ b/board/maxbcm/maxbcm.c
@@ -95,7 +95,7 @@
 	return &maxbcm_ddr_modes[0];
 }
 
-MV_BIN_SERDES_CFG *board_serdes_cfg_get(u8 pex_mode)
+MV_BIN_SERDES_CFG *board_serdes_cfg_get(void)
 {
 	return &maxbcm_serdes_cfg[0];
 }
diff --git a/board/mscc/jr2/jr2.c b/board/mscc/jr2/jr2.c
index 58a4a04..6e5ef4c 100644
--- a/board/mscc/jr2/jr2.c
+++ b/board/mscc/jr2/jr2.c
@@ -6,6 +6,7 @@
 #include <common.h>
 #include <asm/io.h>
 #include <led.h>
+#include <miiphy.h>
 
 enum {
 	BOARD_TYPE_PCB110 = 0xAABBCE00,
@@ -64,6 +65,28 @@
 	}
 }
 
+int board_phy_config(struct phy_device *phydev)
+{
+	if (gd->board_type == BOARD_TYPE_PCB110 ||
+	    gd->board_type == BOARD_TYPE_PCB112) {
+		phy_write(phydev, 0, 31, 0x10);
+		phy_write(phydev, 0, 18, 0x80F0);
+		while (phy_read(phydev, 0, 18) & 0x8000)
+			;
+		phy_write(phydev, 0, 31, 0);
+	}
+	if (gd->board_type == BOARD_TYPE_PCB111) {
+		phy_write(phydev, 0, 31, 0x10);
+		phy_write(phydev, 0, 18, 0x80A0);
+		while (phy_read(phydev, 0, 18) & 0x8000)
+			;
+		phy_write(phydev, 0, 14, 0x800);
+		phy_write(phydev, 0, 31, 0);
+	}
+
+	return 0;
+}
+
 void board_debug_uart_init(void)
 {
 	/* too early for the pinctrl driver, so configure the UART pins here */
diff --git a/board/qca/ap152/Kconfig b/board/qca/ap152/Kconfig
new file mode 100644
index 0000000..f6ad498
--- /dev/null
+++ b/board/qca/ap152/Kconfig
@@ -0,0 +1,15 @@
+if TARGET_AP152
+
+config SYS_VENDOR
+	default "qca"
+
+config SYS_BOARD
+	default "ap152"
+
+config SYS_CONFIG_NAME
+	default "ap152"
+
+config SYS_TEXT_BASE
+	default 0x9f000000
+
+endif
diff --git a/board/qca/ap152/MAINTAINERS b/board/qca/ap152/MAINTAINERS
new file mode 100644
index 0000000..785ec27
--- /dev/null
+++ b/board/qca/ap152/MAINTAINERS
@@ -0,0 +1,6 @@
+AP152 BOARD
+M:	Rosy Song <rosysong@rosinson.com>
+S:	Maintained
+F:	board/qca/ap152/
+F:	include/configs/ap152.h
+F:	configs/ap152_defconfig
diff --git a/board/qca/ap152/Makefile b/board/qca/ap152/Makefile
new file mode 100644
index 0000000..4270afa
--- /dev/null
+++ b/board/qca/ap152/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+obj-y	= ap152.o
diff --git a/board/qca/ap152/ap152.c b/board/qca/ap152/ap152.c
new file mode 100644
index 0000000..30cd565
--- /dev/null
+++ b/board/qca/ap152/ap152.c
@@ -0,0 +1,81 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Rosy Song <rosysong@rosinson.com>
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/addrspace.h>
+#include <asm/types.h>
+#include <mach/ar71xx_regs.h>
+#include <mach/ddr.h>
+#include <mach/ath79.h>
+#include <debug_uart.h>
+
+#define RST_RESET_RTC_RESET_LSB 27
+#define RST_RESET_RTC_RESET_MASK 0x08000000
+#define RST_RESET_RTC_RESET_SET(x) \
+	(((x) << RST_RESET_RTC_RESET_LSB) & RST_RESET_RTC_RESET_MASK)
+
+#ifdef CONFIG_DEBUG_UART_BOARD_INIT
+void board_debug_uart_init(void)
+{
+	void __iomem *regs;
+	u32 val;
+
+	regs = map_physmem(AR71XX_GPIO_BASE, AR71XX_GPIO_SIZE,
+			   MAP_NOCACHE);
+
+	/* UART : RX18, TX22 done
+	 * GPIO18 as input, GPIO22 as output
+	 */
+	val = readl(regs + AR71XX_GPIO_REG_OE);
+	val |= QCA956X_GPIO(18);
+	val &= ~QCA956X_GPIO(22);
+	writel(val, regs + AR71XX_GPIO_REG_OE);
+
+	/*
+	 * Enable GPIO22 as UART0_SOUT
+	 */
+	val = readl(regs + QCA956X_GPIO_REG_OUT_FUNC5);
+	val &= ~QCA956X_GPIO_MUX_MASK(16);
+	val |= QCA956X_GPIO_OUT_MUX_UART0_SOUT << 16;
+	writel(val, regs + QCA956X_GPIO_REG_OUT_FUNC5);
+
+	/*
+	 * Enable GPIO18 as UART0_SIN
+	 */
+	val = readl(regs + QCA956X_GPIO_REG_IN_ENABLE0);
+	val &= ~QCA956X_GPIO_MUX_MASK(8);
+	val |= QCA956X_GPIO_IN_MUX_UART0_SIN << 8;
+	writel(val, regs + QCA956X_GPIO_REG_IN_ENABLE0);
+
+	/*
+	 * Enable GPIO22 output
+	 */
+	val = readl(regs + AR71XX_GPIO_REG_OUT);
+	val |= QCA956X_GPIO(22);
+	writel(val, regs + AR71XX_GPIO_REG_OUT);
+}
+#endif
+
+int board_early_init_f(void)
+{
+	u32 reg;
+	void __iomem *rst_regs = map_physmem(AR71XX_RESET_BASE,
+							 AR71XX_RESET_SIZE, MAP_NOCACHE);
+
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT
+	/* CPU:775, DDR:650, AHB:258 */
+	qca956x_pll_init();
+	qca956x_ddr_init();
+#endif
+
+	/* Take WMAC out of reset */
+	reg = readl(rst_regs + QCA956X_RESET_REG_RESET_MODULE);
+	reg &= (~RST_RESET_RTC_RESET_SET(1));
+	writel(reg, rst_regs + QCA956X_RESET_REG_RESET_MODULE);
+
+	ath79_eth_reset();
+	return 0;
+}
diff --git a/board/solidrun/clearfog/README b/board/solidrun/clearfog/README
index a7bc0d4..0b0e98d 100644
--- a/board/solidrun/clearfog/README
+++ b/board/solidrun/clearfog/README
@@ -17,6 +17,29 @@
 Please use the correct device node for your setup instead
 of "/dev/sdX" here!
 
+Install U-Boot on eMMC:
+-----------------------
+
+The ROM loads the bootloader from eMMC first boot partition at offset 0. This
+is unlike load from SD card that is at offset 512. As a result, the offset of
+the main U-Boot image on the eMMC boot partition changes. Set
+CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR to 0x140 for SPL to load U-Boot from
+the correct location.
+
+To make SPL load the main U-Boot image from the eMMC boot partition enable
+eMMC boot acknowledgement and boot partition with the following U-Boot
+command:
+
+  mmc partconf 0 1 1 0
+
+Install U-Boot on eMMC boot partition from Linux running on Clearfog:
+
+  echo 0 > /sys/block/mmcblk0boot0/force_ro
+  dd if=u-boot-spl.kwb of=/dev/mmcblk0boot0
+
+Note that the SD card is not accessible when the Clearfog SOM has eMMC.
+Consider initial boot from UART (see below).
+
 Boot selection:
 ---------------
 
diff --git a/board/st/stm32mp1/MAINTAINERS b/board/st/stm32mp1/MAINTAINERS
index 48d8fd2..0a2eddb 100644
--- a/board/st/stm32mp1/MAINTAINERS
+++ b/board/st/stm32mp1/MAINTAINERS
@@ -2,7 +2,8 @@
 M:	Patrick Delaunay <patrick.delaunay@st.com>
 L:	uboot-stm32@st-md-mailman.stormreply.com (moderated for non-subscribers)
 S:	Maintained
+F:	arch/arm/dts/stm32mp157*
 F:	board/st/stm32mp1
-F:	include/configs/stm32mp1.h
 F:	configs/stm32mp15_basic_defconfig
-F:	arch/arm/dts/stm32mp157*
+F:	configs/stm32mp15_trusted_defconfig
+F:	include/configs/stm32mp1.h
diff --git a/board/st/stm32mp1/README b/board/st/stm32mp1/README
index 174e6db..1cd3534 100644
--- a/board/st/stm32mp1/README
+++ b/board/st/stm32mp1/README
@@ -28,14 +28,15 @@
 
 And the necessary drivers
 1. I2C
-2. STPMU1
-2. STPMU1 (PMIC and regulator)
+2. STPMIC1 (PMIC and regulator)
 3. Clock, Reset, Sysreset
 4. Fuse
 
 Currently the following boards are supported:
 + stm32mp157c-ev1
 + stm32mp157c-ed1
++ stm32mp157a-dk1
++ stm32mp157c-dk2
 
 3. Boot Sequences
 =================
@@ -45,15 +46,22 @@
 with FSBL = First Stage Bootloader
      SSBL = Second Stage Bootloader
 
-One boot configuration is supported:
+2 boot configurations are supported:
 
-   The "Basic" boot chain (defconfig_file : stm32mp15_basic_defconfig)
+1) The "Trusted" boot chain (defconfig_file : stm32mp15_trusted_defconfig)
+   BootRom => FSBL = Trusted Firmware-A (TF-A) => SSBL = U-Boot
+   TF-A performs a full initialization of Secure peripherals and installs a
+   secure monitor.
+   U-Boot is running in normal world and uses TF-A monitor
+   to access to secure resources
+
+2) The "Basic" boot chain (defconfig_file : stm32mp15_basic_defconfig)
    BootRom => FSBL = U-Boot SPL => SSBL = U-Boot
    SPL has limited security initialisation
    U-Boot is running in secure mode and provide a secure monitor to the kernel
    with only PSCI support (Power State Coordination Interface defined by ARM)
 
-All the STM32MP1 board supported by U-Boot use the same generic board
+All the STM32MP1 boards supported by U-Boot use the same generic board
 stm32mp1 which support all the bootable devices.
 
 Each board is configurated only with the associated device tree.
@@ -64,12 +72,18 @@
 You need to select the appropriate device tree for your board,
 the supported device trees for stm32mp157 are:
 
-+ ev1: eval board with pmic stpmu1 (ev1 = mother board + daughter ed1)
++ ev1: eval board with pmic stpmic1 (ev1 = mother board + daughter ed1)
   dts: stm32mp157c-ev1
 
-+ ed1: daughter board with pmic stpmu1
++ ed1: daughter board with pmic stpmic1
   dts: stm32mp157c-ed1
 
++ dk1: Discovery board
+  dts: stm32mp157a-dk1
+
++ dk2: Discovery board = dk1 with a BT/WiFI combo and a DSI panel
+  dts: stm32mp157c-dk2
+
 5. Build Procedure
 ==================
 
@@ -90,12 +104,14 @@
 	# export KBUILD_OUTPUT=/path/to/output
 
 	for example: use one output directory for each configuration
+	# export KBUILD_OUTPUT=stm32mp15_trusted
 	# export KBUILD_OUTPUT=stm32mp15_basic
 
-4. Configure the U-Boot:
+4. Configure U-Boot:
 
 	# make <defconfig_file>
 
+	- For trusted boot mode : "stm32mp15_trusted_defconfig"
 	- For basic boot mode: "stm32mp15_basic_defconfig"
 
 5. Configure the device-tree and build the U-Boot image:
@@ -104,16 +120,26 @@
 
 
   example:
-     basic boot on ev1
+  a) trusted boot on ev1
+	# export KBUILD_OUTPUT=stm32mp15_trusted
+	# make stm32mp15_trusted_defconfig
+	# make DEVICE_TREE=stm32mp157c-ev1 all
+
+  b) basic boot on ev1
 	# export KBUILD_OUTPUT=stm32mp15_basic
 	# make stm32mp15_basic_defconfig
 	# make DEVICE_TREE=stm32mp157c-ev1 all
 
-     basic boot on ed1
+  c) basic boot on ed1
 	# export KBUILD_OUTPUT=stm32mp15_basic
 	# make stm32mp15_basic_defconfig
 	# make DEVICE_TREE=stm32mp157c-ed1 all
 
+  d) basic boot on dk2
+	# export KBUILD_OUTPUT=stm32mp15_basic
+	# make stm32mp15_basic_defconfig
+	# make DEVICE_TREE=stm32mp157c-dk2 all
+
 6. Output files
 
   BootRom and TF-A expect binaries with STM32 image header
@@ -122,6 +148,11 @@
   So in the output directory (selected by KBUILD_OUTPUT),
   you can found the needed files:
 
+  a) For Trusted boot
+   + FSBL = tf-a.stm32 (provided by TF-A compilation)
+   + SSBL = u-boot.stm32
+
+  b) For Basic boot
    + FSBL = spl/u-boot-spl.stm32
    + SSBL = u-boot.img
 
@@ -135,13 +166,22 @@
  -----------------------------------
   Reserved	0	0	0
   NOR		0	0	1
-  SD-Card	1	1	1
   SD-Card	1	0	1
   eMMC		0	1	0
   NAND		0	1	1
   Recovery	1	1	0
   Recovery	0	0	0
 
+- on board DK1/DK2 with the switch SW1 : BOOT0, BOOT2
+  (BOOT1 forced to 0, NOR not supported)
+
+ --------------------------
+  Boot Mode   BOOT2  BOOT0
+ --------------------------
+  Reserved	1      0
+  SD-Card	1      1
+  Recovery	0      0
+
 Recovery is a boot from serial link (UART/USB) and it is used with
 STM32CubeProgrammer tool to load executable in RAM and to update the flash
 devices available on the board (NOR/NAND/eMMC/SDCARD).
@@ -158,14 +198,14 @@
 - one ssbl partition for U-Boot
 
 Then the minimal GPT partition is:
-   ----- ------- --------- -------------
-  | Num | Name  | Size    |  Content    |
-   ----- ------- -------- --------------
+   ----- ------- --------- --------------
+  | Num | Name  | Size    |  Content     |
+   ----- ------- -------- ---------------
   |  1  | fsbl1 | 256 KiB |  TF-A or SPL |
   |  2  | fsbl2 | 256 KiB |  TF-A or SPL |
-  |  3  | ssbl  | enought |  U-Boot     |
-  |  *  |  -    |  -      |  Boot/Rootfs|
-   ----- ------- --------- -------------
+  |  3  | ssbl  | enought |  U-Boot      |
+  |  *  |  -    |  -      |  Boot/Rootfs |
+   ----- ------- --------- --------------
 
 (*) add bootable partition for extlinux.conf
     following Generic Distribution
@@ -189,7 +229,7 @@
 
 	you can add other partitions for kernel
 	one partition rootfs for example:
-		-n 3:5154:		-c 4:rootfs
+		-n 4:5154:		-c 4:rootfs \
 
   c) copy the FSBL (2 times) and SSBL file on the correct partition.
      in this example in partition 1 to 3
@@ -199,6 +239,11 @@
 	# dd if=u-boot-spl.stm32 of=/dev/mmcblk0p2
 	# dd if=u-boot.img of=/dev/mmcblk0p3
 
+     for trusted boot mode :
+	# dd if=tf-a.stm32 of=/dev/mmcblk0p1
+	# dd if=tf-a.stm32 of=/dev/mmcblk0p2
+	# dd if=u-boot.stm32 of=/dev/mmcblk0p3
+
 To boot from SDCard, select BootPinMode = 1 1 1 and reset.
 
 8. Prepare eMMC
@@ -208,7 +253,7 @@
 In the next example, you need to boot from SDCARD and the images (u-boot-spl.stm32, u-boot.img)
 are presents on SDCARD (mmc 0) in ext4 partition 4 (bootfs).
 
-To boot from SDCard, select BootPinMode = 1 1 1 and reset.
+To boot from SDCard, select BootPinMode = 1 0 1 and reset.
 
 Then you update the eMMC with the next U-Boot command :
 
@@ -227,7 +272,7 @@
 	# mmc write ${fileaddr} 0 200
 	# mmc partconf 1 1 1 0
 
-b) copy U-Boot in first GPT partition of eMMC
+c) copy U-Boot in first GPT partition of eMMC
 
 	# ext4load mmc 0:4 0xC0000000 u-boot.img
 	# mmc dev 1
diff --git a/board/st/stm32mp1/board.c b/board/st/stm32mp1/board.c
index 5f31ea9..5c1acca 100644
--- a/board/st/stm32mp1/board.c
+++ b/board/st/stm32mp1/board.c
@@ -8,7 +8,7 @@
 #include <asm/io.h>
 #include <asm/arch/ddr.h>
 #include <power/pmic.h>
-#include <power/stpmu1.h>
+#include <power/stpmic1.h>
 
 #ifdef CONFIG_DEBUG_UART_BOARD_INIT
 void board_debug_uart_init(void)
@@ -37,64 +37,65 @@
 }
 #endif
 
-#ifdef CONFIG_PMIC_STPMU1
+#ifdef CONFIG_PMIC_STPMIC1
 int board_ddr_power_init(void)
 {
 	struct udevice *dev;
 	int ret;
 
 	ret = uclass_get_device_by_driver(UCLASS_PMIC,
-					  DM_GET_DRIVER(pmic_stpmu1), &dev);
+					  DM_GET_DRIVER(pmic_stpmic1), &dev);
 	if (ret)
 		/* No PMIC on board */
 		return 0;
 
-	/* Set LDO3 to sync mode */
-	ret = pmic_reg_read(dev, STPMU1_LDOX_CTRL_REG(STPMU1_LDO3));
+	/* VTT = Set LDO3 to sync mode */
+	ret = pmic_reg_read(dev, STPMIC1_LDOX_MAIN_CR(STPMIC1_LDO3));
 	if (ret < 0)
 		return ret;
 
-	ret &= ~STPMU1_LDO3_MODE;
-	ret &= ~STPMU1_LDO12356_OUTPUT_MASK;
-	ret |= STPMU1_LDO3_DDR_SEL << STPMU1_LDO12356_OUTPUT_SHIFT;
+	ret &= ~STPMIC1_LDO3_MODE;
+	ret &= ~STPMIC1_LDO12356_VOUT_MASK;
+	ret |= STPMIC1_LDO_VOUT(STPMIC1_LDO3_DDR_SEL);
 
-	ret = pmic_reg_write(dev, STPMU1_LDOX_CTRL_REG(STPMU1_LDO3),
+	ret = pmic_reg_write(dev, STPMIC1_LDOX_MAIN_CR(STPMIC1_LDO3),
 			     ret);
 	if (ret < 0)
 		return ret;
 
-	/* Set BUCK2 to 1.35V */
+	/* VDD_DDR = Set BUCK2 to 1.35V */
 	ret = pmic_clrsetbits(dev,
-			      STPMU1_BUCKX_CTRL_REG(STPMU1_BUCK2),
-			      STPMU1_BUCK_OUTPUT_MASK,
-			      STPMU1_BUCK2_1350000V);
+			      STPMIC1_BUCKX_MAIN_CR(STPMIC1_BUCK2),
+			      STPMIC1_BUCK_VOUT_MASK,
+			      STPMIC1_BUCK2_1350000V);
 	if (ret < 0)
 		return ret;
 
-	/* Enable BUCK2 and VREF */
+	/* Enable VDD_DDR = BUCK2 */
 	ret = pmic_clrsetbits(dev,
-			      STPMU1_BUCKX_CTRL_REG(STPMU1_BUCK2),
-			      STPMU1_BUCK_EN, STPMU1_BUCK_EN);
+			      STPMIC1_BUCKX_MAIN_CR(STPMIC1_BUCK2),
+			      STPMIC1_BUCK_ENA, STPMIC1_BUCK_ENA);
 	if (ret < 0)
 		return ret;
 
-	mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS);
+	mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
 
-	ret = pmic_clrsetbits(dev, STPMU1_VREF_CTRL_REG,
-			      STPMU1_VREF_EN, STPMU1_VREF_EN);
+	/* Enable VREF */
+	ret = pmic_clrsetbits(dev, STPMIC1_REFDDR_MAIN_CR,
+			      STPMIC1_VREF_ENA, STPMIC1_VREF_ENA);
 	if (ret < 0)
 		return ret;
 
-	mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS);
+	mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
 
 	/* Enable LDO3 */
 	ret = pmic_clrsetbits(dev,
-			      STPMU1_LDOX_CTRL_REG(STPMU1_LDO3),
-			      STPMU1_LDO_EN, STPMU1_LDO_EN);
+			      STPMIC1_LDOX_MAIN_CR(STPMIC1_LDO3),
+			      STPMIC1_LDO_ENA, STPMIC1_LDO_ENA);
 	if (ret < 0)
 		return ret;
 
-	mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS);
+	mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
 
 	return 0;
 }
diff --git a/board/st/stm32mp1/spl.c b/board/st/stm32mp1/spl.c
index f3db0d6..a7844f2 100644
--- a/board/st/stm32mp1/spl.c
+++ b/board/st/stm32mp1/spl.c
@@ -11,22 +11,22 @@
 #include <asm/io.h>
 #include <post.h>
 #include <power/pmic.h>
-#include <power/stpmu1.h>
+#include <power/stpmic1.h>
 #include <asm/arch/ddr.h>
 
 void spl_board_init(void)
 {
 	/* Keep vdd on during the reset cycle */
-#if defined(CONFIG_PMIC_STPMU1) && defined(CONFIG_SPL_POWER_SUPPORT)
+#if defined(CONFIG_PMIC_STPMIC1) && defined(CONFIG_SPL_POWER_SUPPORT)
 	struct udevice *dev;
 	int ret;
 
 	ret = uclass_get_device_by_driver(UCLASS_PMIC,
-					  DM_GET_DRIVER(pmic_stpmu1), &dev);
+					  DM_GET_DRIVER(pmic_stpmic1), &dev);
 	if (!ret)
 		pmic_clrsetbits(dev,
-				STPMU1_MASK_RESET_BUCK,
-				STPMU1_MASK_RESET_BUCK3,
-				STPMU1_MASK_RESET_BUCK3);
+				STPMIC1_BUCKS_MRST_CR,
+				STPMIC1_MRST_BUCK(STPMIC1_BUCK3),
+				STPMIC1_MRST_BUCK(STPMIC1_BUCK3));
 #endif
 }
diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c
index 54feca0..24d299a 100644
--- a/board/st/stm32mp1/stm32mp1.c
+++ b/board/st/stm32mp1/stm32mp1.c
@@ -2,20 +2,57 @@
 /*
  * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
  */
-#include <config.h>
 #include <common.h>
-#include <led.h>
+#include <adc.h>
+#include <config.h>
 #include <clk.h>
 #include <dm.h>
 #include <generic-phy.h>
+#include <led.h>
+#include <misc.h>
 #include <phy.h>
 #include <reset.h>
+#include <syscon.h>
 #include <usb.h>
-#include <asm/arch/stm32.h>
 #include <asm/io.h>
+#include <asm/gpio.h>
+#include <asm/arch/stm32.h>
 #include <power/regulator.h>
 #include <usb/dwc2_udc.h>
 
+/* SYSCFG registers */
+#define SYSCFG_BOOTR		0x00
+#define SYSCFG_PMCSETR		0x04
+#define SYSCFG_IOCTRLSETR	0x18
+#define SYSCFG_ICNR		0x1C
+#define SYSCFG_CMPCR		0x20
+#define SYSCFG_CMPENSETR	0x24
+#define SYSCFG_PMCCLRR		0x44
+
+#define SYSCFG_BOOTR_BOOT_MASK		GENMASK(2, 0)
+#define SYSCFG_BOOTR_BOOTPD_SHIFT	4
+
+#define SYSCFG_IOCTRLSETR_HSLVEN_TRACE		BIT(0)
+#define SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI	BIT(1)
+#define SYSCFG_IOCTRLSETR_HSLVEN_ETH		BIT(2)
+#define SYSCFG_IOCTRLSETR_HSLVEN_SDMMC		BIT(3)
+#define SYSCFG_IOCTRLSETR_HSLVEN_SPI		BIT(4)
+
+#define SYSCFG_CMPCR_SW_CTRL		BIT(1)
+#define SYSCFG_CMPCR_READY		BIT(8)
+
+#define SYSCFG_CMPENSETR_MPU_EN		BIT(0)
+
+#define SYSCFG_PMCSETR_ETH_CLK_SEL	BIT(16)
+#define SYSCFG_PMCSETR_ETH_REF_CLK_SEL	BIT(17)
+
+#define SYSCFG_PMCSETR_ETH_SELMII	BIT(20)
+
+#define SYSCFG_PMCSETR_ETH_SEL_MASK	GENMASK(23, 21)
+#define SYSCFG_PMCSETR_ETH_SEL_GMII_MII	(0 << 21)
+#define SYSCFG_PMCSETR_ETH_SEL_RGMII	(1 << 21)
+#define SYSCFG_PMCSETR_ETH_SEL_RMII	(4 << 21)
+
 /*
  * Get a global data pointer
  */
@@ -26,6 +63,98 @@
 #define STM32MP_GGPIO 0x38
 #define STM32MP_GGPIO_VBUS_SENSING BIT(21)
 
+#define USB_WARNING_LOW_THRESHOLD_UV	660000
+#define USB_START_LOW_THRESHOLD_UV	1230000
+#define USB_START_HIGH_THRESHOLD_UV	2100000
+
+int checkboard(void)
+{
+	int ret;
+	char *mode;
+	u32 otp;
+	struct udevice *dev;
+	const char *fdt_compat;
+	int fdt_compat_len;
+
+	if (IS_ENABLED(CONFIG_STM32MP1_TRUSTED))
+		mode = "trusted";
+	else
+		mode = "basic";
+
+	printf("Board: stm32mp1 in %s mode", mode);
+	fdt_compat = fdt_getprop(gd->fdt_blob, 0, "compatible",
+				 &fdt_compat_len);
+	if (fdt_compat && fdt_compat_len)
+		printf(" (%s)", fdt_compat);
+	puts("\n");
+
+	ret = uclass_get_device_by_driver(UCLASS_MISC,
+					  DM_GET_DRIVER(stm32mp_bsec),
+					  &dev);
+
+	if (!ret)
+		ret = misc_read(dev, STM32_BSEC_SHADOW(BSEC_OTP_BOARD),
+				&otp, sizeof(otp));
+	if (!ret && otp) {
+		printf("Board: MB%04x Var%d Rev.%c-%02d\n",
+		       otp >> 16,
+		       (otp >> 12) & 0xF,
+		       ((otp >> 8) & 0xF) - 1 + 'A',
+		       otp & 0xF);
+	}
+
+	return 0;
+}
+
+static void board_key_check(void)
+{
+#if defined(CONFIG_FASTBOOT) || defined(CONFIG_CMD_STM32PROG)
+	ofnode node;
+	struct gpio_desc gpio;
+	enum forced_boot_mode boot_mode = BOOT_NORMAL;
+
+	node = ofnode_path("/config");
+	if (!ofnode_valid(node)) {
+		debug("%s: no /config node?\n", __func__);
+		return;
+	}
+#ifdef CONFIG_FASTBOOT
+	if (gpio_request_by_name_nodev(node, "st,fastboot-gpios", 0,
+				       &gpio, GPIOD_IS_IN)) {
+		debug("%s: could not find a /config/st,fastboot-gpios\n",
+		      __func__);
+	} else {
+		if (dm_gpio_get_value(&gpio)) {
+			puts("Fastboot key pressed, ");
+			boot_mode = BOOT_FASTBOOT;
+		}
+
+		dm_gpio_free(NULL, &gpio);
+	}
+#endif
+#ifdef CONFIG_CMD_STM32PROG
+	if (gpio_request_by_name_nodev(node, "st,stm32prog-gpios", 0,
+				       &gpio, GPIOD_IS_IN)) {
+		debug("%s: could not find a /config/st,stm32prog-gpios\n",
+		      __func__);
+	} else {
+		if (dm_gpio_get_value(&gpio)) {
+			puts("STM32Programmer key pressed, ");
+			boot_mode = BOOT_STM32PROG;
+		}
+		dm_gpio_free(NULL, &gpio);
+	}
+#endif
+
+	if (boot_mode != BOOT_NORMAL) {
+		puts("entering download mode...\n");
+		clrsetbits_le32(TAMP_BOOT_CONTEXT,
+				TAMP_BOOT_FORCED_MASK,
+				boot_mode);
+	}
+#endif
+}
+
 static struct dwc2_plat_otg_data stm32mp_otg_data = {
 	.usb_gusbcfg = STM32MP_GUSBCFG,
 };
@@ -167,9 +296,148 @@
 clk_err:
 	clk_disable(&clk);
 
+	return ret;
+}
+
+static int get_led(struct udevice **dev, char *led_string)
+{
+	char *led_name;
+	int ret;
+
+	led_name = fdtdec_get_config_string(gd->fdt_blob, led_string);
+	if (!led_name) {
+		pr_debug("%s: could not find %s config string\n",
+			 __func__, led_string);
+		return -ENOENT;
+	}
+	ret = led_get_by_label(led_name, dev);
+	if (ret) {
+		debug("%s: get=%d\n", __func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int setup_led(enum led_state_t cmd)
+{
+	struct udevice *dev;
+	int ret;
+
+	ret = get_led(&dev, "u-boot,boot-led");
+	if (ret)
+		return ret;
+
+	ret = led_set_state(dev, cmd);
 	return ret;
 }
 
+static int board_check_usb_power(void)
+{
+	struct ofnode_phandle_args adc_args;
+	struct udevice *adc;
+	struct udevice *led;
+	ofnode node;
+	unsigned int raw;
+	int max_uV = 0;
+	int ret, uV, adc_count;
+	u8 i, nb_blink;
+
+	node = ofnode_path("/config");
+	if (!ofnode_valid(node)) {
+		debug("%s: no /config node?\n", __func__);
+		return -ENOENT;
+	}
+
+	/*
+	 * Retrieve the ADC channels devices and get measurement
+	 * for each of them
+	 */
+	adc_count = ofnode_count_phandle_with_args(node, "st,adc_usb_pd",
+						   "#io-channel-cells");
+	if (adc_count < 0) {
+		if (adc_count == -ENOENT)
+			return 0;
+
+		pr_err("%s: can't find adc channel (%d)\n", __func__,
+		       adc_count);
+
+		return adc_count;
+	}
+
+	for (i = 0; i < adc_count; i++) {
+		if (ofnode_parse_phandle_with_args(node, "st,adc_usb_pd",
+						   "#io-channel-cells", 0, i,
+						   &adc_args)) {
+			pr_debug("%s: can't find /config/st,adc_usb_pd\n",
+				 __func__);
+			return 0;
+		}
+
+		ret = uclass_get_device_by_ofnode(UCLASS_ADC, adc_args.node,
+						  &adc);
+
+		if (ret) {
+			pr_err("%s: Can't get adc device(%d)\n", __func__,
+			       ret);
+			return ret;
+		}
+
+		ret = adc_channel_single_shot(adc->name, adc_args.args[0],
+					      &raw);
+		if (ret) {
+			pr_err("%s: single shot failed for %s[%d]!\n",
+			       __func__, adc->name, adc_args.args[0]);
+			return ret;
+		}
+		/* Convert to uV */
+		if (!adc_raw_to_uV(adc, raw, &uV)) {
+			if (uV > max_uV)
+				max_uV = uV;
+			pr_debug("%s: %s[%02d] = %u, %d uV\n", __func__,
+				 adc->name, adc_args.args[0], raw, uV);
+		} else {
+			pr_err("%s: Can't get uV value for %s[%d]\n",
+			       __func__, adc->name, adc_args.args[0]);
+		}
+	}
+
+	/*
+	 * If highest value is inside 1.23 Volts and 2.10 Volts, that means
+	 * board is plugged on an USB-C 3A power supply and boot process can
+	 * continue.
+	 */
+	if (max_uV > USB_START_LOW_THRESHOLD_UV &&
+	    max_uV < USB_START_HIGH_THRESHOLD_UV)
+		return 0;
+
+	/* Display warning message and make u-boot,error-led blinking */
+	pr_err("\n*******************************************\n");
+
+	if (max_uV < USB_WARNING_LOW_THRESHOLD_UV) {
+		pr_err("*   WARNING 500mA power supply detected   *\n");
+		nb_blink = 2;
+	} else {
+		pr_err("* WARNING 1.5A power supply detected      *\n");
+		nb_blink = 3;
+	}
+
+	pr_err("* Current too low, use a 3A power supply! *\n");
+	pr_err("*******************************************\n\n");
+
+	ret = get_led(&led, "u-boot,error-led");
+	if (ret)
+		return ret;
+
+	for (i = 0; i < nb_blink * 2; i++) {
+		led_set_state(led, LEDST_TOGGLE);
+		mdelay(125);
+	}
+	led_set_state(led, LEDST_ON);
+
+	return 0;
+}
+
 int board_usb_cleanup(int index, enum usb_init_type init)
 {
 	/* Reset usbotg */
@@ -180,19 +448,146 @@
 	return 0;
 }
 
-int board_late_init(void)
+static void sysconf_init(void)
 {
-	return 0;
+#ifndef CONFIG_STM32MP1_TRUSTED
+	u8 *syscfg;
+#ifdef CONFIG_DM_REGULATOR
+	struct udevice *pwr_dev;
+	struct udevice *pwr_reg;
+	struct udevice *dev;
+	int ret;
+	u32 otp = 0;
+#endif
+	u32 bootr;
+
+	syscfg = (u8 *)syscon_get_first_range(STM32MP_SYSCON_SYSCFG);
+
+	/* interconnect update : select master using the port 1 */
+	/* LTDC = AXI_M9 */
+	/* GPU  = AXI_M8 */
+	/* today information is hardcoded in U-Boot */
+	writel(BIT(9), syscfg + SYSCFG_ICNR);
+
+	/* disable Pull-Down for boot pin connected to VDD */
+	bootr = readl(syscfg + SYSCFG_BOOTR);
+	bootr &= ~(SYSCFG_BOOTR_BOOT_MASK << SYSCFG_BOOTR_BOOTPD_SHIFT);
+	bootr |= (bootr & SYSCFG_BOOTR_BOOT_MASK) << SYSCFG_BOOTR_BOOTPD_SHIFT;
+	writel(bootr, syscfg + SYSCFG_BOOTR);
+
+#ifdef CONFIG_DM_REGULATOR
+	/* High Speed Low Voltage Pad mode Enable for SPI, SDMMC, ETH, QSPI
+	 * and TRACE. Needed above ~50MHz and conditioned by AFMUX selection.
+	 * The customer will have to disable this for low frequencies
+	 * or if AFMUX is selected but the function not used, typically for
+	 * TRACE. Otherwise, impact on power consumption.
+	 *
+	 * WARNING:
+	 *   enabling High Speed mode while VDD>2.7V
+	 *   with the OTP product_below_2v5 (OTP 18, BIT 13)
+	 *   erroneously set to 1 can damage the IC!
+	 *   => U-Boot set the register only if VDD < 2.7V (in DT)
+	 *      but this value need to be consistent with board design
+	 */
+	ret = syscon_get_by_driver_data(STM32MP_SYSCON_PWR, &pwr_dev);
+	if (!ret) {
+		ret = uclass_get_device_by_driver(UCLASS_MISC,
+						  DM_GET_DRIVER(stm32mp_bsec),
+						  &dev);
+		if (ret) {
+			pr_err("Can't find stm32mp_bsec driver\n");
+			return;
+		}
+
+		ret = misc_read(dev, STM32_BSEC_SHADOW(18), &otp, 4);
+		if (!ret)
+			otp = otp & BIT(13);
+
+		/* get VDD = pwr-supply */
+		ret = device_get_supply_regulator(pwr_dev, "pwr-supply",
+						  &pwr_reg);
+
+		/* check if VDD is Low Voltage */
+		if (!ret) {
+			if (regulator_get_value(pwr_reg) < 2700000) {
+				writel(SYSCFG_IOCTRLSETR_HSLVEN_TRACE |
+				       SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI |
+				       SYSCFG_IOCTRLSETR_HSLVEN_ETH |
+				       SYSCFG_IOCTRLSETR_HSLVEN_SDMMC |
+				       SYSCFG_IOCTRLSETR_HSLVEN_SPI,
+				       syscfg + SYSCFG_IOCTRLSETR);
+
+				if (!otp)
+					pr_err("product_below_2v5=0: HSLVEN protected by HW\n");
+			} else {
+				if (otp)
+					pr_err("product_below_2v5=1: HSLVEN update is destructive, no update as VDD>2.7V\n");
+			}
+		} else {
+			debug("VDD unknown");
+		}
+	}
+#endif
+
+	/* activate automatic I/O compensation
+	 * warning: need to ensure CSI enabled and ready in clock driver
+	 */
+	writel(SYSCFG_CMPENSETR_MPU_EN, syscfg + SYSCFG_CMPENSETR);
+
+	while (!(readl(syscfg + SYSCFG_CMPCR) & SYSCFG_CMPCR_READY))
+		;
+	clrbits_le32(syscfg + SYSCFG_CMPCR, SYSCFG_CMPCR_SW_CTRL);
+#endif
 }
 
 /* board dependent setup after realloc */
 int board_init(void)
 {
+	struct udevice *dev;
+
 	/* address of boot parameters */
 	gd->bd->bi_boot_params = STM32_DDR_BASE + 0x100;
 
+	/* probe all PINCTRL for hog */
+	for (uclass_first_device(UCLASS_PINCTRL, &dev);
+	     dev;
+	     uclass_next_device(&dev)) {
+		pr_debug("probe pincontrol = %s\n", dev->name);
+	}
+
+	board_key_check();
+
+	sysconf_init();
+
 	if (IS_ENABLED(CONFIG_LED))
 		led_default_state();
 
 	return 0;
 }
+
+int board_late_init(void)
+{
+#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
+	const void *fdt_compat;
+	int fdt_compat_len;
+
+	fdt_compat = fdt_getprop(gd->fdt_blob, 0, "compatible",
+				 &fdt_compat_len);
+	if (fdt_compat && fdt_compat_len) {
+		if (strncmp(fdt_compat, "st,", 3) != 0)
+			env_set("board_name", fdt_compat);
+		else
+			env_set("board_name", fdt_compat + 3);
+	}
+#endif
+
+	/* for DK1/DK2 boards */
+	board_check_usb_power();
+
+	return 0;
+}
+
+void board_quiesce_devices(void)
+{
+	setup_led(LEDST_OFF);
+}
diff --git a/board/sunxi/MAINTAINERS b/board/sunxi/MAINTAINERS
index 8e2f90f..338f374 100644
--- a/board/sunxi/MAINTAINERS
+++ b/board/sunxi/MAINTAINERS
@@ -341,6 +341,11 @@
 S:	Maintained
 F:	configs/Nintendo_NES_Classic_Edition_defconfig
 
+OCEANIC 5205 5INMFD BOARD
+M:	Jagan Teki <jagan@amarulasolutions.com>
+S:	Maintained
+F:	configs/oceanic_5205_5inmfd_defconfig
+
 OLIMEX A20-SOM204 BOARD
 M:	Stefan Mavrodiev <stefan@olimex.com>
 S:	Maintained
@@ -348,7 +353,7 @@
 F:	configs/A20-Olimex-SOM204-EVB-eMMC_defconfig
 
 ORANGEPI LITE2 BOARD
-M:	Jagan Teki <jagan@openedev.com>
+M:	Jagan Teki <jagan@amarulasolutions.com>
 S:	Maintained
 F:	configs/orangepi_lite2_defconfig
 
diff --git a/board/theadorable/theadorable.c b/board/theadorable/theadorable.c
index dd6def5..d423503 100644
--- a/board/theadorable/theadorable.c
+++ b/board/theadorable/theadorable.c
@@ -1,11 +1,15 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
- * Copyright (C) 2015-2016 Stefan Roese <sr@denx.de>
+ * Copyright (C) 2015-2019 Stefan Roese <sr@denx.de>
  */
 
 #include <common.h>
+#include <console.h>
 #include <i2c.h>
 #include <pci.h>
+#if !defined(CONFIG_SPL_BUILD)
+#include <bootcount.h>
+#endif
 #include <asm/gpio.h>
 #include <asm/io.h>
 #include <asm/arch/cpu.h>
@@ -42,6 +46,7 @@
 #define STM_I2C_BUS	1
 #define STM_I2C_ADDR	0x27
 #define REBOOT_DELAY	1000		/* reboot-delay in ms */
+#define ABORT_TIMEOUT	3000		/* 3 seconds reboot abort timeout */
 
 /* DDR3 static configuration */
 static MV_DRAM_MC_INIT ddr3_theadorable[MV_MAX_DDR3_STATIC_SIZE] = {
@@ -127,15 +132,15 @@
 	return &board_ddr_modes[0];
 }
 
-MV_BIN_SERDES_CFG *board_serdes_cfg_get(u8 pex_mode)
+MV_BIN_SERDES_CFG *board_serdes_cfg_get(void)
 {
 	return &theadorable_serdes_cfg[0];
 }
 
 u8 board_sat_r_get(u8 dev_num, u8 reg)
 {
-	/* Bit 0 enables PCI 2.0 link capabilities instead of PCI 1.x */
-	return 0x01;
+	/* Bit x enables PCI 2.0 link capabilities instead of PCI 1.x */
+	return 0xe;	/* PEX port 0 is PCIe Gen1, PEX port 1..3 PCIe Gen2 */
 }
 
 int board_early_init_f(void)
@@ -218,7 +223,7 @@
 }
 #endif
 
-#ifdef CONFIG_BOARD_LATE_INIT
+#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_BOARD_LATE_INIT)
 int board_late_init(void)
 {
 	pci_dev_t bdf;
@@ -232,6 +237,7 @@
 	 */
 	bdf = pci_find_device(PCI_VENDOR_ID_PLX, 0x8619, 0);
 	if (bdf == -1) {
+		unsigned long start_time = get_timer(0);
 		u8 i2c_buf[8];
 		int ret;
 
@@ -239,6 +245,28 @@
 		bootcount = bootcount_load();
 		printf("Failed to find PLX PEX-switch (bootcount=%ld)\n",
 		       bootcount);
+
+		/*
+		 * The user can exit this boot-loop in the error case by
+		 * hitting Ctrl-C. So wait some time for this key here.
+		 */
+		printf("Continue booting with Ctrl-C, otherwise rebooting\n");
+		do {
+			/* Handle control-c and timeouts */
+			if (ctrlc()) {
+				printf("PEX error boot-loop aborted!\n");
+				return 0;
+			}
+		} while (get_timer(start_time) < ABORT_TIMEOUT);
+
+
+		/*
+		 * At this stage the bootcounter has not been incremented
+		 * yet. We need to do this manually here to get an actually
+		 * working bootcounter in this error case.
+		 */
+		bootcount_inc();
+
 		if (bootcount > PEX_SWITCH_NOT_FOUNT_LIMIT) {
 			printf("Issuing power-switch via uC!\n");
 
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 0b07b3b..2bdbfcb 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -1101,6 +1101,12 @@
 	help
 	  VirtIO block device support
 
+config CMD_WDT
+	bool "wdt"
+	depends on WDT
+	help
+	  This provides commands to control the watchdog timer devices.
+
 config CMD_AXI
 	bool "axi"
 	depends on AXI
diff --git a/cmd/Makefile b/cmd/Makefile
index acb85f4..6b1c6b0 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -142,6 +142,7 @@
 obj-$(CONFIG_CMD_UNIVERSE) += universe.o
 obj-$(CONFIG_CMD_UNZIP) += unzip.o
 obj-$(CONFIG_CMD_VIRTIO) += virtio.o
+obj-$(CONFIG_CMD_WDT) += wdt.o
 obj-$(CONFIG_CMD_LZMADEC) += lzmadec.o
 
 obj-$(CONFIG_CMD_USB) += usb.o disk.o
diff --git a/cmd/sf.c b/cmd/sf.c
index 738ef0e..6ccf98a 100644
--- a/cmd/sf.c
+++ b/cmd/sf.c
@@ -81,14 +81,13 @@
 {
 	unsigned int bus = CONFIG_SF_DEFAULT_BUS;
 	unsigned int cs = CONFIG_SF_DEFAULT_CS;
+	/* In DM mode, defaults speed and mode will be taken from DT */
 	unsigned int speed = CONFIG_SF_DEFAULT_SPEED;
 	unsigned int mode = CONFIG_SF_DEFAULT_MODE;
 	char *endp;
 #ifdef CONFIG_DM_SPI_FLASH
 	struct udevice *new, *bus_dev;
 	int ret;
-	/* In DM mode defaults will be taken from DT */
-	speed = 0, mode = 0;
 #else
 	struct spi_flash *new;
 #endif
diff --git a/cmd/wdt.c b/cmd/wdt.c
new file mode 100644
index 0000000..647d989
--- /dev/null
+++ b/cmd/wdt.c
@@ -0,0 +1,174 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Watchdog commands
+ *
+ * Copyright (c) 2019 Michael Walle <michael@walle.cc>
+ */
+
+#include <common.h>
+#include <command.h>
+#include <dm.h>
+#include <wdt.h>
+
+static struct udevice *currdev;
+
+static int do_wdt_list(cmd_tbl_t *cmdtp, int flag, int argc,
+		       char *const argv[])
+{
+	struct udevice *dev;
+	struct uclass *uc;
+	int ret;
+
+	ret = uclass_get(UCLASS_WDT, &uc);
+	if (ret)
+		return CMD_RET_FAILURE;
+
+	uclass_foreach_dev(dev, uc)
+		printf("%s (%s)\n", dev->name, dev->driver->name);
+
+	return CMD_RET_SUCCESS;
+}
+
+static int do_wdt_dev(cmd_tbl_t *cmdtp, int flag, int argc,
+		      char *const argv[])
+{
+	int ret;
+
+	if (argc > 1) {
+		ret = uclass_get_device_by_name(UCLASS_WDT, argv[1], &currdev);
+		if (ret) {
+			printf("Can't get the watchdog timer: %s\n", argv[1]);
+			return CMD_RET_FAILURE;
+		}
+	} else {
+		if (!currdev) {
+			printf("No watchdog timer device set!\n");
+			return CMD_RET_FAILURE;
+		}
+		printf("dev: %s\n", currdev->name);
+	}
+
+	return CMD_RET_SUCCESS;
+}
+
+static int check_currdev(void)
+{
+	if (!currdev) {
+		printf("No device set, use 'wdt dev' first\n");
+		return CMD_RET_FAILURE;
+	}
+	return 0;
+}
+
+static int do_wdt_start(cmd_tbl_t *cmdtp, int flag, int argc,
+			char *const argv[])
+{
+	int ret;
+	u64 timeout;
+	ulong flags = 0;
+
+	if (argc < 2)
+		return CMD_RET_USAGE;
+
+	ret = check_currdev();
+	if (ret)
+		return ret;
+
+	timeout = simple_strtoull(argv[1], NULL, 0);
+	if (argc > 2)
+		flags = simple_strtoul(argv[2], NULL, 0);
+
+	ret = wdt_start(currdev, timeout, flags);
+	if (ret == -ENOSYS) {
+		printf("Starting watchdog timer not supported.\n");
+		return CMD_RET_FAILURE;
+	} else if (ret) {
+		printf("Starting watchdog timer failed (%d)\n", ret);
+		return CMD_RET_FAILURE;
+	}
+
+	return CMD_RET_SUCCESS;
+}
+
+static int do_wdt_stop(cmd_tbl_t *cmdtp, int flag, int argc,
+		       char *const argv[])
+{
+	int ret;
+
+	ret = check_currdev();
+	if (ret)
+		return ret;
+
+	ret = wdt_stop(currdev);
+	if (ret == -ENOSYS) {
+		printf("Stopping watchdog timer not supported.\n");
+		return CMD_RET_FAILURE;
+	} else if (ret) {
+		printf("Stopping watchdog timer failed (%d)\n", ret);
+		return CMD_RET_FAILURE;
+	}
+
+	return CMD_RET_SUCCESS;
+}
+
+static int do_wdt_reset(cmd_tbl_t *cmdtp, int flag, int argc,
+			char *const argv[])
+{
+	int ret;
+
+	ret = check_currdev();
+	if (ret)
+		return ret;
+
+	ret = wdt_reset(currdev);
+	if (ret == -ENOSYS) {
+		printf("Resetting watchdog timer not supported.\n");
+		return CMD_RET_FAILURE;
+	} else if (ret) {
+		printf("Resetting watchdog timer failed (%d)\n", ret);
+		return CMD_RET_FAILURE;
+	}
+
+	return CMD_RET_SUCCESS;
+}
+
+static int do_wdt_expire(cmd_tbl_t *cmdtp, int flag, int argc,
+			 char *const argv[])
+{
+	int ret;
+	ulong flags = 0;
+
+	ret = check_currdev();
+	if (ret)
+		return ret;
+
+	if (argc > 1)
+		flags = simple_strtoul(argv[1], NULL, 0);
+
+	ret = wdt_expire_now(currdev, flags);
+	if (ret == -ENOSYS) {
+		printf("Expiring watchdog timer not supported.\n");
+		return CMD_RET_FAILURE;
+	} else if (ret) {
+		printf("Expiring watchdog timer failed (%d)\n", ret);
+		return CMD_RET_FAILURE;
+	}
+
+	return CMD_RET_SUCCESS;
+}
+
+static char wdt_help_text[] =
+	"list - list watchdog devices\n"
+	"wdt dev [<name>] - get/set current watchdog device\n"
+	"wdt start <timeout ms> [flags] - start watchdog timer\n"
+	"wdt stop - stop watchdog timer\n"
+	"wdt reset - reset watchdog timer\n"
+	"wdt expire [flags] - expire watchdog timer immediately\n";
+
+U_BOOT_CMD_WITH_SUBCMDS(wdt, "Watchdog sub-system", wdt_help_text,
+	U_BOOT_SUBCMD_MKENT(list, 1, 1, do_wdt_list),
+	U_BOOT_SUBCMD_MKENT(dev, 2, 1, do_wdt_dev),
+	U_BOOT_SUBCMD_MKENT(start, 3, 1, do_wdt_start),
+	U_BOOT_SUBCMD_MKENT(stop, 1, 1, do_wdt_stop),
+	U_BOOT_SUBCMD_MKENT(reset, 1, 1, do_wdt_reset),
+	U_BOOT_SUBCMD_MKENT(expire, 2, 1, do_wdt_expire));
diff --git a/common/fdt_support.c b/common/fdt_support.c
index 42583e3..ab08a01 100644
--- a/common/fdt_support.c
+++ b/common/fdt_support.c
@@ -456,12 +456,6 @@
 	if (!banks)
 		return 0;
 
-	for (i = 0; i < banks; i++)
-		if (start[i] == 0 && size[i] == 0)
-			break;
-
-	banks = i;
-
 	len = fdt_pack_reg(blob, tmp, start, size, banks);
 
 	err = fdt_setprop(blob, nodeoffset, "reg", tmp, len);
diff --git a/common/spl/spl_spi.c b/common/spl/spl_spi.c
index 8cd4830..9b74473 100644
--- a/common/spl/spl_spi.c
+++ b/common/spl/spl_spi.c
@@ -77,6 +77,8 @@
 
 	/*
 	 * Load U-Boot image from SPI flash into RAM
+	 * In DM mode: defaults speed and mode will be
+	 * taken from DT when available
 	 */
 
 	flash = spi_flash_probe(CONFIG_SF_DEFAULT_BUS,
diff --git a/common/usb_kbd.c b/common/usb_kbd.c
index 020f0d4..cc99c6b 100644
--- a/common/usb_kbd.c
+++ b/common/usb_kbd.c
@@ -145,6 +145,12 @@
 	data->usb_kbd_buffer[data->usb_in_pointer] = c;
 }
 
+static void usb_kbd_put_sequence(struct usb_kbd_pdata *data, char *s)
+{
+	for (; *s; s++)
+		usb_kbd_put_queue(data, *s);
+}
+
 /*
  * Set the LEDs. Since this is used in the irq routine, the control job is
  * issued with a timeout of 0. This means, that the job is queued without
@@ -235,9 +241,25 @@
 	}
 
 	/* Report keycode if any */
-	if (keycode) {
+	if (keycode)
 		debug("%c", keycode);
+
+	switch (keycode) {
+	case 0x0e:					/* Down arrow key */
+		usb_kbd_put_sequence(data, "\e[B");
+		break;
+	case 0x10:					/* Up arrow key */
+		usb_kbd_put_sequence(data, "\e[A");
+		break;
+	case 0x06:					/* Right arrow key */
+		usb_kbd_put_sequence(data, "\e[C");
+		break;
+	case 0x02:					/* Left arrow key */
+		usb_kbd_put_sequence(data, "\e[D");
+		break;
+	default:
 		usb_kbd_put_queue(data, keycode);
+		break;
 	}
 
 	return 0;
diff --git a/configs/ap152_defconfig b/configs/ap152_defconfig
new file mode 100644
index 0000000..21cb6eb
--- /dev/null
+++ b/configs/ap152_defconfig
@@ -0,0 +1,49 @@
+CONFIG_MIPS=y
+CONFIG_SYS_TEXT_BASE=0x9F000000
+CONFIG_SYS_MALLOC_F_LEN=0x800
+CONFIG_SYS_CACHE_SIZE_AUTO=y
+CONFIG_DEBUG_UART_BOARD_INIT=y
+CONFIG_DEBUG_UART_BASE=0xb8020000
+CONFIG_DEBUG_UART_CLOCK=25000000
+CONFIG_ARCH_ATH79=y
+CONFIG_TARGET_AP152=y
+CONFIG_DEBUG_UART=y
+CONFIG_BOOTDELAY=3
+CONFIG_USE_BOOTARGS=y
+CONFIG_BOOTARGS="console=ttyS0,115200 root=/dev/mtdblock2 rootfstype=squashfs"
+CONFIG_DISPLAY_CPUINFO=y
+CONFIG_BOARD_EARLY_INIT_F=y
+CONFIG_SYS_PROMPT="ap152 # "
+# CONFIG_CMD_BDI is not set
+# CONFIG_CMD_CONSOLE is not set
+# CONFIG_CMD_ELF is not set
+# CONFIG_CMD_XIMG is not set
+# CONFIG_CMD_EXPORTENV is not set
+# CONFIG_CMD_IMPORTENV is not set
+# CONFIG_CMD_EDITENV is not set
+# CONFIG_CMD_CRC32 is not set
+CONFIG_CMD_MEMTEST=y
+# CONFIG_CMD_FLASH is not set
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_MTDPARTS=y
+CONFIG_MTDIDS_DEFAULT="nor0=spi-flash.0"
+CONFIG_MTDPARTS_DEFAULT="mtdparts=spi-flash.0:256k(u-boot),64k(u-boot-env),6336k(rootfs),1472k(uImage),64k(ART)"
+# CONFIG_ISO_PARTITION is not set
+CONFIG_DEFAULT_DEVICE_TREE="ap152"
+CONFIG_ENV_IS_IN_SPI_FLASH=y
+# CONFIG_NET is not set
+CONFIG_DM_SPI_FLASH=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_BAR=y
+CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_SPI_FLASH_DATAFLASH=y
+CONFIG_SPI_FLASH_MTD=y
+CONFIG_PINCTRL=y
+CONFIG_DM_SERIAL=y
+CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_SYS_NS16550=y
+CONFIG_SPI=y
+CONFIG_DM_SPI=y
+CONFIG_ATH79_SPI=y
+CONFIG_LZMA=y
diff --git a/configs/bananapi_m2_plus_h3_defconfig b/configs/bananapi_m2_plus_h3_defconfig
index 597618f..4e47346 100644
--- a/configs/bananapi_m2_plus_h3_defconfig
+++ b/configs/bananapi_m2_plus_h3_defconfig
@@ -3,8 +3,6 @@
 CONFIG_SPL=y
 CONFIG_MACH_SUN8I_H3=y
 CONFIG_DRAM_CLK=672
-CONFIG_DRAM_ZQ=3881979
-CONFIG_DRAM_ODT_EN=y
 CONFIG_MACPWR="PD6"
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 CONFIG_NR_DRAM_BANKS=1
diff --git a/configs/bananapi_m2_plus_h5_defconfig b/configs/bananapi_m2_plus_h5_defconfig
index e7c10db..29dd892 100644
--- a/configs/bananapi_m2_plus_h5_defconfig
+++ b/configs/bananapi_m2_plus_h5_defconfig
@@ -3,8 +3,6 @@
 CONFIG_SPL=y
 CONFIG_MACH_SUN50I_H5=y
 CONFIG_DRAM_CLK=672
-CONFIG_DRAM_ZQ=3881979
-CONFIG_DRAM_ODT_EN=y
 CONFIG_MACPWR="PD6"
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 CONFIG_NR_DRAM_BANKS=1
diff --git a/configs/bananapi_m2_zero_defconfig b/configs/bananapi_m2_zero_defconfig
index 91302eb..8546674 100644
--- a/configs/bananapi_m2_zero_defconfig
+++ b/configs/bananapi_m2_zero_defconfig
@@ -3,8 +3,6 @@
 CONFIG_SPL=y
 CONFIG_MACH_SUN8I_H3=y
 CONFIG_DRAM_CLK=408
-CONFIG_DRAM_ZQ=3881979
-CONFIG_DRAM_ODT_EN=y
 CONFIG_MMC0_CD_PIN=""
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 # CONFIG_CMD_FLASH is not set
diff --git a/configs/bcm963158_ram_defconfig b/configs/bcm963158_ram_defconfig
index fc55e98..5659249 100644
--- a/configs/bcm963158_ram_defconfig
+++ b/configs/bcm963158_ram_defconfig
@@ -20,6 +20,7 @@
 # CONFIG_CMD_LZMADEC is not set
 # CONFIG_CMD_UNZIP is not set
 # CONFIG_CMD_FLASH is not set
+CONFIG_CMD_GPIO=y
 CONFIG_CMD_CACHE=y
 CONFIG_DOS_PARTITION=y
 CONFIG_ISO_PARTITION=y
@@ -28,6 +29,8 @@
 # CONFIG_NET is not set
 CONFIG_BLK=y
 CONFIG_CLK=y
+CONFIG_DM_GPIO=y
+CONFIG_BCM6345_GPIO=y
 # CONFIG_MMC is not set
 CONFIG_SPECIFY_CONSOLE_INDEX=y
 # CONFIG_SPL_SERIAL_PRESENT is not set
diff --git a/configs/bcm968380gerg_ram_defconfig b/configs/bcm968380gerg_ram_defconfig
index 61661bd..fa9dc85 100644
--- a/configs/bcm968380gerg_ram_defconfig
+++ b/configs/bcm968380gerg_ram_defconfig
@@ -24,6 +24,7 @@
 # CONFIG_CMD_CRC32 is not set
 CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_FLASH is not set
+CONFIG_CMD_GPIO=y
 # CONFIG_CMD_LOADS is not set
 # CONFIG_CMD_MISC is not set
 CONFIG_DEFAULT_DEVICE_TREE="brcm,bcm968380gerg"
@@ -31,6 +32,7 @@
 # CONFIG_DM_DEVICE_REMOVE is not set
 CONFIG_HAVE_BLOCK_DEVICE=y
 CONFIG_DM_GPIO=y
+CONFIG_BCM6345_GPIO=y
 CONFIG_LED=y
 CONFIG_LED_BCM6328=y
 CONFIG_LED_BLINK=y
diff --git a/configs/bcm968580xref_ram_defconfig b/configs/bcm968580xref_ram_defconfig
index e8cb3a0..456ece7 100644
--- a/configs/bcm968580xref_ram_defconfig
+++ b/configs/bcm968580xref_ram_defconfig
@@ -15,6 +15,7 @@
 CONFIG_DISPLAY_BOARDINFO_LATE=y
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_BOOTEFI_SELFTEST=y
+CONFIG_CMD_GPIO=y
 CONFIG_DOS_PARTITION=y
 CONFIG_ISO_PARTITION=y
 CONFIG_EFI_PARTITION=y
@@ -22,6 +23,8 @@
 # CONFIG_NET is not set
 CONFIG_BLK=y
 CONFIG_CLK=y
+CONFIG_DM_GPIO=y
+CONFIG_BCM6345_GPIO=y
 # CONFIG_MMC is not set
 CONFIG_SPECIFY_CONSOLE_INDEX=y
 # CONFIG_SPL_SERIAL_PRESENT is not set
diff --git a/configs/da850_am18xxevm_defconfig b/configs/da850_am18xxevm_defconfig
index b8c16ba..4192241 100644
--- a/configs/da850_am18xxevm_defconfig
+++ b/configs/da850_am18xxevm_defconfig
@@ -39,10 +39,6 @@
 CONFIG_DEFAULT_DEVICE_TREE="da850-evm"
 CONFIG_SPL_OF_PLATDATA=y
 CONFIG_ENV_IS_IN_SPI_FLASH=y
-CONFIG_USE_ENV_SPI_MAX_HZ=y
-CONFIG_ENV_SPI_MAX_HZ=0
-CONFIG_USE_ENV_SPI_MODE=y
-CONFIG_ENV_SPI_MODE=0
 CONFIG_DM=y
 CONFIG_SPL_DM=y
 CONFIG_DA8XX_GPIO=y
diff --git a/configs/da850evm_defconfig b/configs/da850evm_defconfig
index 4083dcb..4b09ba1 100644
--- a/configs/da850evm_defconfig
+++ b/configs/da850evm_defconfig
@@ -43,10 +43,6 @@
 CONFIG_SPL_OF_CONTROL=y
 CONFIG_DEFAULT_DEVICE_TREE="da850-evm"
 CONFIG_ENV_IS_IN_SPI_FLASH=y
-CONFIG_USE_ENV_SPI_MAX_HZ=y
-CONFIG_ENV_SPI_MAX_HZ=0
-CONFIG_USE_ENV_SPI_MODE=y
-CONFIG_ENV_SPI_MODE=0
 CONFIG_DM=y
 CONFIG_SPL_DM=y
 CONFIG_SPL_DM_SEQ_ALIAS=y
diff --git a/configs/db-88f6820-amc_defconfig b/configs/db-88f6820-amc_defconfig
index dcf2a25..e8ba518 100644
--- a/configs/db-88f6820-amc_defconfig
+++ b/configs/db-88f6820-amc_defconfig
@@ -41,7 +41,7 @@
 CONFIG_EFI_PARTITION=y
 # CONFIG_PARTITION_UUIDS is not set
 # CONFIG_SPL_PARTITION_UUIDS is not set
-CONFIG_DEFAULT_DEVICE_TREE="armada-385-amc"
+CONFIG_DEFAULT_DEVICE_TREE="armada-385-db-88f6820-amc"
 CONFIG_ENV_IS_IN_SPI_FLASH=y
 CONFIG_USE_ENV_SPI_MAX_HZ=y
 CONFIG_ENV_SPI_MAX_HZ=50000000
diff --git a/configs/db-mv784mp-gp_defconfig b/configs/db-mv784mp-gp_defconfig
index 98e47ee..078bd23 100644
--- a/configs/db-mv784mp-gp_defconfig
+++ b/configs/db-mv784mp-gp_defconfig
@@ -46,6 +46,7 @@
 CONFIG_ENV_SPI_MAX_HZ=50000000
 CONFIG_SPL_OF_TRANSLATE=y
 CONFIG_SATA_MV=y
+CONFIG_BLK=y
 # CONFIG_MMC is not set
 CONFIG_NAND=y
 CONFIG_NAND_PXA3XX=y
diff --git a/configs/db-xc3-24g4xg_defconfig b/configs/db-xc3-24g4xg_defconfig
new file mode 100644
index 0000000..0285ccaa
--- /dev/null
+++ b/configs/db-xc3-24g4xg_defconfig
@@ -0,0 +1,55 @@
+CONFIG_ARM=y
+CONFIG_ARCH_MVEBU=y
+CONFIG_SYS_TEXT_BASE=0x00800000
+CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_TARGET_DB_XC3_24G4XG=y
+CONFIG_BUILD_TARGET="u-boot.kwb"
+CONFIG_SYS_CONSOLE_INFO_QUIET=y
+CONFIG_CMD_MEMTEST=y
+CONFIG_SYS_ALT_MEMTEST=y
+# CONFIG_CMD_FLASH is not set
+CONFIG_CMD_I2C=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_USB=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_TFTPPUT=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_TIME=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_CMD_UBI=y
+CONFIG_DEFAULT_DEVICE_TREE="armada-xp-db-xc3-24g4xg"
+CONFIG_ENV_IS_IN_SPI_FLASH=y
+CONFIG_SPL_OF_TRANSLATE=y
+CONFIG_BLK=y
+CONFIG_DM_I2C=y
+CONFIG_SYS_I2C_MVTWSI=y
+# CONFIG_MMC is not set
+CONFIG_MTD=y
+CONFIG_MTD_DEVICE=y
+CONFIG_NAND=y
+CONFIG_NAND_PXA3XX=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_SFDP_SUPPORT=y
+CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_SPI_FLASH_SST=y
+# CONFIG_SPI_FLASH_USE_4K_SECTORS is not set
+CONFIG_PCI=y
+CONFIG_PCI_MVEBU=y
+CONFIG_SYS_NS16550=y
+CONFIG_KIRKWOOD_SPI=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_HOST_ETHER=y
+CONFIG_USB_ETHER_ASIX=y
+CONFIG_USB_ETHER_RTL8152=y
+CONFIG_USB_ETHER_SMSC95XX=y
diff --git a/configs/dns325_defconfig b/configs/dns325_defconfig
index 5a76698..ba8b053 100644
--- a/configs/dns325_defconfig
+++ b/configs/dns325_defconfig
@@ -30,6 +30,7 @@
 CONFIG_ENV_IS_IN_NAND=y
 CONFIG_DM=y
 CONFIG_MVSATA_IDE=y
+CONFIG_BLK=y
 # CONFIG_MMC is not set
 CONFIG_MVGBE=y
 CONFIG_MII=y
@@ -37,5 +38,6 @@
 CONFIG_RTC_MV=y
 CONFIG_SYS_NS16550=y
 CONFIG_USB=y
+CONFIG_DM_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
diff --git a/configs/dreamplug_defconfig b/configs/dreamplug_defconfig
index 8202848..eae36f9 100644
--- a/configs/dreamplug_defconfig
+++ b/configs/dreamplug_defconfig
@@ -27,6 +27,7 @@
 CONFIG_ENV_SPI_MAX_HZ=50000000
 CONFIG_DM=y
 CONFIG_MVSATA_IDE=y
+CONFIG_BLK=y
 # CONFIG_MMC is not set
 CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
@@ -40,5 +41,6 @@
 CONFIG_DM_SPI=y
 CONFIG_KIRKWOOD_SPI=y
 CONFIG_USB=y
+CONFIG_DM_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
diff --git a/configs/ds109_defconfig b/configs/ds109_defconfig
index 29d5f98..22996e8 100644
--- a/configs/ds109_defconfig
+++ b/configs/ds109_defconfig
@@ -22,6 +22,7 @@
 CONFIG_ENV_SPI_MAX_HZ=50000000
 CONFIG_DM=y
 CONFIG_MVSATA_IDE=y
+CONFIG_BLK=y
 CONFIG_DM_I2C=y
 CONFIG_SYS_I2C_MVTWSI=y
 # CONFIG_MMC is not set
@@ -37,5 +38,6 @@
 CONFIG_DM_SPI=y
 CONFIG_KIRKWOOD_SPI=y
 CONFIG_USB=y
+CONFIG_DM_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_FS_EXT4=y
diff --git a/configs/ds414_defconfig b/configs/ds414_defconfig
index 62cad53..9e93649 100644
--- a/configs/ds414_defconfig
+++ b/configs/ds414_defconfig
@@ -43,6 +43,7 @@
 CONFIG_ENV_SPI_MAX_HZ=50000000
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_SPL_OF_TRANSLATE=y
+CONFIG_BLK=y
 # CONFIG_MMC is not set
 CONFIG_MTD_DEVICE=y
 CONFIG_SPI_FLASH=y
diff --git a/configs/emlid_neutis_n5_devboard_defconfig b/configs/emlid_neutis_n5_devboard_defconfig
index 3df0ca1..19e8d79 100644
--- a/configs/emlid_neutis_n5_devboard_defconfig
+++ b/configs/emlid_neutis_n5_devboard_defconfig
@@ -4,6 +4,7 @@
 CONFIG_MACH_SUN50I_H5=y
 CONFIG_DRAM_CLK=408
 CONFIG_DRAM_ZQ=3881977
+# CONFIG_DRAM_ODT_EN is not set
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 CONFIG_NR_DRAM_BANKS=1
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
diff --git a/configs/goflexhome_defconfig b/configs/goflexhome_defconfig
index c04bf0e..568b74f 100644
--- a/configs/goflexhome_defconfig
+++ b/configs/goflexhome_defconfig
@@ -31,6 +31,7 @@
 CONFIG_ENV_IS_IN_NAND=y
 CONFIG_DM=y
 CONFIG_MVSATA_IDE=y
+CONFIG_BLK=y
 # CONFIG_MMC is not set
 CONFIG_MVGBE=y
 CONFIG_MII=y
@@ -38,5 +39,6 @@
 CONFIG_RTC_MV=y
 CONFIG_SYS_NS16550=y
 CONFIG_USB=y
+CONFIG_DM_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
diff --git a/configs/guruplug_defconfig b/configs/guruplug_defconfig
index 9998e48..8ae7e20 100644
--- a/configs/guruplug_defconfig
+++ b/configs/guruplug_defconfig
@@ -31,6 +31,7 @@
 CONFIG_ENV_IS_IN_NAND=y
 CONFIG_DM=y
 CONFIG_MVSATA_IDE=y
+CONFIG_BLK=y
 # CONFIG_MMC is not set
 CONFIG_MVGBE=y
 CONFIG_MII=y
@@ -38,6 +39,7 @@
 CONFIG_RTC_MV=y
 CONFIG_SYS_NS16550=y
 CONFIG_USB=y
+CONFIG_DM_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
 CONFIG_LZMA=y
diff --git a/configs/libretech_all_h3_cc_h2_plus_defconfig b/configs/libretech_all_h3_cc_h2_plus_defconfig
index 8f31448..3bccd60 100644
--- a/configs/libretech_all_h3_cc_h2_plus_defconfig
+++ b/configs/libretech_all_h3_cc_h2_plus_defconfig
@@ -3,8 +3,6 @@
 CONFIG_SPL=y
 CONFIG_MACH_SUN8I_H3=y
 CONFIG_DRAM_CLK=672
-CONFIG_DRAM_ZQ=3881979
-CONFIG_DRAM_ODT_EN=y
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 CONFIG_NR_DRAM_BANKS=1
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
diff --git a/configs/libretech_all_h3_cc_h3_defconfig b/configs/libretech_all_h3_cc_h3_defconfig
index e5e0f59..c00ab01 100644
--- a/configs/libretech_all_h3_cc_h3_defconfig
+++ b/configs/libretech_all_h3_cc_h3_defconfig
@@ -3,8 +3,6 @@
 CONFIG_SPL=y
 CONFIG_MACH_SUN8I_H3=y
 CONFIG_DRAM_CLK=672
-CONFIG_DRAM_ZQ=3881979
-CONFIG_DRAM_ODT_EN=y
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 CONFIG_NR_DRAM_BANKS=1
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
diff --git a/configs/libretech_all_h3_cc_h5_defconfig b/configs/libretech_all_h3_cc_h5_defconfig
index e4a93bd..5843f34 100644
--- a/configs/libretech_all_h3_cc_h5_defconfig
+++ b/configs/libretech_all_h3_cc_h5_defconfig
@@ -3,8 +3,6 @@
 CONFIG_SPL=y
 CONFIG_MACH_SUN50I_H5=y
 CONFIG_DRAM_CLK=672
-CONFIG_DRAM_ZQ=3881979
-CONFIG_DRAM_ODT_EN=y
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 CONFIG_NR_DRAM_BANKS=1
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
diff --git a/configs/linkit-smart-7688-ram_defconfig b/configs/linkit-smart-7688-ram_defconfig
index 2d3ab7e..649db0f 100644
--- a/configs/linkit-smart-7688-ram_defconfig
+++ b/configs/linkit-smart-7688-ram_defconfig
@@ -20,17 +20,22 @@
 # CONFIG_CMD_FLASH is not set
 CONFIG_CMD_GPIO=y
 # CONFIG_CMD_LOADS is not set
+CONFIG_CMD_MTD=y
+CONFIG_CMD_PART=y
 CONFIG_CMD_SF=y
 CONFIG_CMD_SPI=y
+CONFIG_CMD_USB=y
 CONFIG_CMD_DHCP=y
 CONFIG_CMD_MII=y
 CONFIG_CMD_PING=y
 CONFIG_CMD_TIME=y
+CONFIG_CMD_FS_GENERIC=y
+# CONFIG_DOS_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="linkit-smart-7688"
 CONFIG_ENV_IS_IN_SPI_FLASH=y
 CONFIG_NET_RANDOM_ETHADDR=y
 # CONFIG_DM_DEVICE_REMOVE is not set
-CONFIG_HAVE_BLOCK_DEVICE=y
+CONFIG_BLK=y
 CONFIG_CLK=y
 CONFIG_LED=y
 CONFIG_LED_BLINK=y
@@ -46,6 +51,7 @@
 CONFIG_PHY_FIXED=y
 CONFIG_MT7628_ETH=y
 CONFIG_PHY=y
+CONFIG_MT76X8_USB_PHY=y
 CONFIG_POWER_DOMAIN=y
 CONFIG_RAM=y
 CONFIG_DM_RESET=y
@@ -54,5 +60,12 @@
 CONFIG_SPI=y
 CONFIG_MT7621_SPI=y
 CONFIG_SYSRESET_SYSCON=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_GENERIC=y
+CONFIG_USB_STORAGE=y
+CONFIG_FS_EXT4=y
+CONFIG_FS_FAT=y
 CONFIG_LZMA=y
 CONFIG_LZO=y
diff --git a/configs/linkit-smart-7688_defconfig b/configs/linkit-smart-7688_defconfig
index ad34aaf..41aa900 100644
--- a/configs/linkit-smart-7688_defconfig
+++ b/configs/linkit-smart-7688_defconfig
@@ -24,17 +24,22 @@
 # CONFIG_CMD_FLASH is not set
 CONFIG_CMD_GPIO=y
 # CONFIG_CMD_LOADS is not set
+CONFIG_CMD_MTD=y
+CONFIG_CMD_PART=y
 CONFIG_CMD_SF=y
 CONFIG_CMD_SPI=y
+CONFIG_CMD_USB=y
 CONFIG_CMD_DHCP=y
 CONFIG_CMD_MII=y
 CONFIG_CMD_PING=y
 CONFIG_CMD_TIME=y
+CONFIG_CMD_FS_GENERIC=y
+# CONFIG_DOS_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="linkit-smart-7688"
 CONFIG_ENV_IS_IN_SPI_FLASH=y
 CONFIG_NET_RANDOM_ETHADDR=y
 # CONFIG_DM_DEVICE_REMOVE is not set
-CONFIG_HAVE_BLOCK_DEVICE=y
+CONFIG_BLK=y
 CONFIG_CLK=y
 CONFIG_LED=y
 CONFIG_LED_BLINK=y
@@ -50,6 +55,7 @@
 CONFIG_PHY_FIXED=y
 CONFIG_MT7628_ETH=y
 CONFIG_PHY=y
+CONFIG_MT76X8_USB_PHY=y
 CONFIG_POWER_DOMAIN=y
 CONFIG_RAM=y
 CONFIG_DM_RESET=y
@@ -58,5 +64,12 @@
 CONFIG_SPI=y
 CONFIG_MT7621_SPI=y
 CONFIG_SYSRESET_SYSCON=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_GENERIC=y
+CONFIG_USB_STORAGE=y
+CONFIG_FS_EXT4=y
+CONFIG_FS_FAT=y
 CONFIG_LZMA=y
 CONFIG_LZO=y
diff --git a/configs/lschlv2_defconfig b/configs/lschlv2_defconfig
index 16d9c92..c550798 100644
--- a/configs/lschlv2_defconfig
+++ b/configs/lschlv2_defconfig
@@ -16,7 +16,7 @@
 CONFIG_MISC_INIT_R=y
 # CONFIG_DISPLAY_BOARDINFO is not set
 # CONFIG_CMD_FLASH is not set
-CONFIG_CMD_IDE=y
+CONFIG_CMD_SATA=y
 CONFIG_CMD_SF=y
 CONFIG_CMD_SPI=y
 CONFIG_CMD_USB=y
@@ -26,7 +26,8 @@
 CONFIG_ENV_IS_IN_SPI_FLASH=y
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_DM=y
-CONFIG_MVSATA_IDE=y
+CONFIG_SATA_MV=y
+CONFIG_BLK=y
 # CONFIG_MMC is not set
 CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
@@ -39,4 +40,5 @@
 CONFIG_DM_SPI=y
 CONFIG_KIRKWOOD_SPI=y
 CONFIG_USB=y
+CONFIG_DM_USB=y
 CONFIG_USB_EHCI_HCD=y
diff --git a/configs/lsxhl_defconfig b/configs/lsxhl_defconfig
index b6eba4a..efcce45 100644
--- a/configs/lsxhl_defconfig
+++ b/configs/lsxhl_defconfig
@@ -16,7 +16,7 @@
 CONFIG_MISC_INIT_R=y
 # CONFIG_DISPLAY_BOARDINFO is not set
 # CONFIG_CMD_FLASH is not set
-CONFIG_CMD_IDE=y
+CONFIG_CMD_SATA=y
 CONFIG_CMD_SF=y
 CONFIG_CMD_SPI=y
 CONFIG_CMD_USB=y
@@ -26,7 +26,8 @@
 CONFIG_ENV_IS_IN_SPI_FLASH=y
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_DM=y
-CONFIG_MVSATA_IDE=y
+CONFIG_SATA_MV=y
+CONFIG_BLK=y
 # CONFIG_MMC is not set
 CONFIG_DM_SPI_FLASH=y
 CONFIG_SPI_FLASH=y
@@ -39,4 +40,5 @@
 CONFIG_DM_SPI=y
 CONFIG_KIRKWOOD_SPI=y
 CONFIG_USB=y
+CONFIG_DM_USB=y
 CONFIG_USB_EHCI_HCD=y
diff --git a/configs/mscc_jr2_defconfig b/configs/mscc_jr2_defconfig
index 95562b7..d6e4bd4 100644
--- a/configs/mscc_jr2_defconfig
+++ b/configs/mscc_jr2_defconfig
@@ -28,7 +28,10 @@
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_SF=y
 CONFIG_CMD_SPI=y
-# CONFIG_CMD_NET is not set
+CONFIG_CMD_DHCP=y
+# CONFIG_NET_TFTP_VARS is not set
+# CONFIG_CMD_NFS is not set
+CONFIG_CMD_PING=y
 CONFIG_CMD_MTDPARTS=y
 CONFIG_MTDIDS_DEFAULT="nor0=spi_flash"
 CONFIG_MTDPARTS_DEFAULT="mtdparts=spi_flash:1m(UBoot),256k(Env),256k(Env.bk)"
@@ -38,10 +41,6 @@
 CONFIG_DTB_RESELECT=y
 CONFIG_MULTI_DTB_FIT=y
 CONFIG_ENV_IS_IN_SPI_FLASH=y
-CONFIG_USE_ENV_SPI_MAX_HZ=y
-CONFIG_ENV_SPI_MAX_HZ=0
-CONFIG_USE_ENV_SPI_MODE=y
-CONFIG_ENV_SPI_MODE=0
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_CLK=y
 CONFIG_DM_GPIO=y
@@ -66,3 +65,4 @@
 CONFIG_SPI=y
 CONFIG_DM_SPI=y
 CONFIG_LZMA=y
+CONFIG_MSCC_JR2_SWITCH=y
diff --git a/configs/mscc_luton_defconfig b/configs/mscc_luton_defconfig
index 162a514..0fdd9b8 100644
--- a/configs/mscc_luton_defconfig
+++ b/configs/mscc_luton_defconfig
@@ -44,10 +44,6 @@
 CONFIG_DTB_RESELECT=y
 CONFIG_MULTI_DTB_FIT=y
 CONFIG_ENV_IS_IN_SPI_FLASH=y
-CONFIG_USE_ENV_SPI_MAX_HZ=y
-CONFIG_ENV_SPI_MAX_HZ=0
-CONFIG_USE_ENV_SPI_MODE=y
-CONFIG_ENV_SPI_MODE=0
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_CLK=y
 CONFIG_DM_GPIO=y
diff --git a/configs/mscc_ocelot_defconfig b/configs/mscc_ocelot_defconfig
index b0dcfaf..edc476d 100644
--- a/configs/mscc_ocelot_defconfig
+++ b/configs/mscc_ocelot_defconfig
@@ -43,10 +43,6 @@
 CONFIG_DTB_RESELECT=y
 CONFIG_MULTI_DTB_FIT=y
 CONFIG_ENV_IS_IN_SPI_FLASH=y
-CONFIG_USE_ENV_SPI_MAX_HZ=y
-CONFIG_ENV_SPI_MAX_HZ=0
-CONFIG_USE_ENV_SPI_MODE=y
-CONFIG_ENV_SPI_MODE=0
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_CLK=y
 CONFIG_DM_GPIO=y
diff --git a/configs/mscc_serval_defconfig b/configs/mscc_serval_defconfig
index f2c9563..146188b 100644
--- a/configs/mscc_serval_defconfig
+++ b/configs/mscc_serval_defconfig
@@ -35,10 +35,6 @@
 CONFIG_DTB_RESELECT=y
 CONFIG_MULTI_DTB_FIT=y
 CONFIG_ENV_IS_IN_SPI_FLASH=y
-CONFIG_USE_ENV_SPI_MAX_HZ=y
-CONFIG_ENV_SPI_MAX_HZ=0
-CONFIG_USE_ENV_SPI_MODE=y
-CONFIG_ENV_SPI_MODE=0
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_CLK=y
 CONFIG_DM_GPIO=y
diff --git a/configs/mscc_servalt_defconfig b/configs/mscc_servalt_defconfig
index 027aaa4..924cf6a 100644
--- a/configs/mscc_servalt_defconfig
+++ b/configs/mscc_servalt_defconfig
@@ -24,7 +24,6 @@
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_SF=y
 CONFIG_CMD_SPI=y
-# CONFIG_CMD_NET is not set
 CONFIG_CMD_MTDPARTS=y
 CONFIG_MTDIDS_DEFAULT="nor0=spi_flash"
 CONFIG_MTDPARTS_DEFAULT="mtdparts=spi_flash:1m(UBoot),256k(Env),256k(Env.bk)"
@@ -33,10 +32,6 @@
 CONFIG_DTB_RESELECT=y
 CONFIG_MULTI_DTB_FIT=y
 CONFIG_ENV_IS_IN_SPI_FLASH=y
-CONFIG_USE_ENV_SPI_MAX_HZ=y
-CONFIG_ENV_SPI_MAX_HZ=0
-CONFIG_USE_ENV_SPI_MODE=y
-CONFIG_ENV_SPI_MODE=0
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_CLK=y
 CONFIG_DM_GPIO=y
@@ -59,3 +54,8 @@
 CONFIG_SPI=y
 CONFIG_DM_SPI=y
 CONFIG_LZMA=y
+CONFIG_CMD_DHCP=y
+# CONFIG_NET_TFTP_VARS is not set
+# CONFIG_CMD_NFS is not set
+CONFIG_CMD_PING=y
+CONFIG_MSCC_SERVALT_SWITCH=y
diff --git a/configs/nanopi_m1_defconfig b/configs/nanopi_m1_defconfig
index b3a7870..af7fa0b 100644
--- a/configs/nanopi_m1_defconfig
+++ b/configs/nanopi_m1_defconfig
@@ -3,8 +3,6 @@
 CONFIG_SPL=y
 CONFIG_MACH_SUN8I_H3=y
 CONFIG_DRAM_CLK=408
-CONFIG_DRAM_ZQ=3881979
-CONFIG_DRAM_ODT_EN=y
 CONFIG_NR_DRAM_BANKS=1
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 # CONFIG_CMD_FLASH is not set
diff --git a/configs/nanopi_m1_plus_defconfig b/configs/nanopi_m1_plus_defconfig
index b83cdf2..84e1525 100644
--- a/configs/nanopi_m1_plus_defconfig
+++ b/configs/nanopi_m1_plus_defconfig
@@ -3,8 +3,6 @@
 CONFIG_SPL=y
 CONFIG_MACH_SUN8I_H3=y
 CONFIG_DRAM_CLK=408
-CONFIG_DRAM_ZQ=3881979
-CONFIG_DRAM_ODT_EN=y
 CONFIG_MMC0_CD_PIN="PH13"
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 CONFIG_NR_DRAM_BANKS=1
diff --git a/configs/nanopi_neo2_defconfig b/configs/nanopi_neo2_defconfig
index 9de893a..2d44135 100644
--- a/configs/nanopi_neo2_defconfig
+++ b/configs/nanopi_neo2_defconfig
@@ -4,6 +4,7 @@
 CONFIG_MACH_SUN50I_H5=y
 CONFIG_DRAM_CLK=672
 CONFIG_DRAM_ZQ=3881977
+# CONFIG_DRAM_ODT_EN is not set
 CONFIG_NR_DRAM_BANKS=1
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 # CONFIG_CMD_FLASH is not set
diff --git a/configs/nanopi_neo_air_defconfig b/configs/nanopi_neo_air_defconfig
index 33f9c07..bd099c8 100644
--- a/configs/nanopi_neo_air_defconfig
+++ b/configs/nanopi_neo_air_defconfig
@@ -3,8 +3,6 @@
 CONFIG_SPL=y
 CONFIG_MACH_SUN8I_H3=y
 CONFIG_DRAM_CLK=408
-CONFIG_DRAM_ZQ=3881979
-CONFIG_DRAM_ODT_EN=y
 # CONFIG_VIDEO_DE2 is not set
 CONFIG_NR_DRAM_BANKS=1
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
diff --git a/configs/nanopi_neo_defconfig b/configs/nanopi_neo_defconfig
index 40f5bd1..074b172 100644
--- a/configs/nanopi_neo_defconfig
+++ b/configs/nanopi_neo_defconfig
@@ -3,8 +3,6 @@
 CONFIG_SPL=y
 CONFIG_MACH_SUN8I_H3=y
 CONFIG_DRAM_CLK=408
-CONFIG_DRAM_ZQ=3881979
-CONFIG_DRAM_ODT_EN=y
 # CONFIG_VIDEO_DE2 is not set
 CONFIG_NR_DRAM_BANKS=1
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
diff --git a/configs/nanopi_neo_plus2_defconfig b/configs/nanopi_neo_plus2_defconfig
index 88c76a5..11cb8f6 100644
--- a/configs/nanopi_neo_plus2_defconfig
+++ b/configs/nanopi_neo_plus2_defconfig
@@ -4,6 +4,7 @@
 CONFIG_MACH_SUN50I_H5=y
 CONFIG_DRAM_CLK=408
 CONFIG_DRAM_ZQ=3881977
+# CONFIG_DRAM_ODT_EN is not set
 CONFIG_MACPWR="PD6"
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 CONFIG_NR_DRAM_BANKS=1
diff --git a/configs/nas220_defconfig b/configs/nas220_defconfig
index 6bd308b..a244b8d 100644
--- a/configs/nas220_defconfig
+++ b/configs/nas220_defconfig
@@ -31,6 +31,7 @@
 CONFIG_ENV_IS_IN_NAND=y
 CONFIG_DM=y
 CONFIG_MVSATA_IDE=y
+CONFIG_BLK=y
 # CONFIG_MMC is not set
 CONFIG_MVGBE=y
 CONFIG_MII=y
@@ -38,5 +39,6 @@
 CONFIG_RTC_MV=y
 CONFIG_SYS_NS16550=y
 CONFIG_USB=y
+CONFIG_DM_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
diff --git a/configs/oceanic_5205_5inmfd_defconfig b/configs/oceanic_5205_5inmfd_defconfig
new file mode 100644
index 0000000..34fe6f5
--- /dev/null
+++ b/configs/oceanic_5205_5inmfd_defconfig
@@ -0,0 +1,20 @@
+CONFIG_ARM=y
+CONFIG_ARCH_SUNXI=y
+CONFIG_SPL=y
+CONFIG_MACH_SUN50I=y
+CONFIG_RESERVE_ALLWINNER_BOOT0_HEADER=y
+CONFIG_SUNXI_DRAM_LPDDR3_STOCK=y
+CONFIG_DRAM_CLK=552
+CONFIG_DRAM_ZQ=3881949
+CONFIG_MMC0_CD_PIN=""
+CONFIG_SPL_SPI_SUNXI=y
+CONFIG_NR_DRAM_BANKS=1
+# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+# CONFIG_CMD_FLASH is not set
+# CONFIG_SPL_DOS_PARTITION is not set
+# CONFIG_SPL_EFI_PARTITION is not set
+CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-oceanic-5205-5inmfd"
+CONFIG_SUN8I_EMAC=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/orangepi_2_defconfig b/configs/orangepi_2_defconfig
index ab6566e..ce3cc83 100644
--- a/configs/orangepi_2_defconfig
+++ b/configs/orangepi_2_defconfig
@@ -4,8 +4,6 @@
 CONFIG_SPL=y
 CONFIG_MACH_SUN8I_H3=y
 CONFIG_DRAM_CLK=672
-CONFIG_DRAM_ZQ=3881979
-CONFIG_DRAM_ODT_EN=y
 CONFIG_USB1_VBUS_PIN="PG13"
 CONFIG_NR_DRAM_BANKS=1
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
diff --git a/configs/orangepi_lite_defconfig b/configs/orangepi_lite_defconfig
index 1092a85..490f5a3 100644
--- a/configs/orangepi_lite_defconfig
+++ b/configs/orangepi_lite_defconfig
@@ -3,8 +3,6 @@
 CONFIG_SPL=y
 CONFIG_MACH_SUN8I_H3=y
 CONFIG_DRAM_CLK=672
-CONFIG_DRAM_ZQ=3881979
-CONFIG_DRAM_ODT_EN=y
 CONFIG_NR_DRAM_BANKS=1
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 # CONFIG_CMD_FLASH is not set
diff --git a/configs/orangepi_one_defconfig b/configs/orangepi_one_defconfig
index 404fdd9..949fc5d 100644
--- a/configs/orangepi_one_defconfig
+++ b/configs/orangepi_one_defconfig
@@ -3,8 +3,6 @@
 CONFIG_SPL=y
 CONFIG_MACH_SUN8I_H3=y
 CONFIG_DRAM_CLK=672
-CONFIG_DRAM_ZQ=3881979
-CONFIG_DRAM_ODT_EN=y
 CONFIG_NR_DRAM_BANKS=1
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 # CONFIG_CMD_FLASH is not set
diff --git a/configs/orangepi_pc2_defconfig b/configs/orangepi_pc2_defconfig
index ad83738..a5bac5b 100644
--- a/configs/orangepi_pc2_defconfig
+++ b/configs/orangepi_pc2_defconfig
@@ -4,6 +4,7 @@
 CONFIG_MACH_SUN50I_H5=y
 CONFIG_DRAM_CLK=672
 CONFIG_DRAM_ZQ=3881977
+# CONFIG_DRAM_ODT_EN is not set
 CONFIG_MACPWR="PD6"
 CONFIG_SPL_SPI_SUNXI=y
 CONFIG_NR_DRAM_BANKS=1
diff --git a/configs/orangepi_pc_defconfig b/configs/orangepi_pc_defconfig
index de11df7..79d6237 100644
--- a/configs/orangepi_pc_defconfig
+++ b/configs/orangepi_pc_defconfig
@@ -3,8 +3,6 @@
 CONFIG_SPL=y
 CONFIG_MACH_SUN8I_H3=y
 CONFIG_DRAM_CLK=624
-CONFIG_DRAM_ZQ=3881979
-CONFIG_DRAM_ODT_EN=y
 CONFIG_NR_DRAM_BANKS=1
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_SPL_I2C_SUPPORT=y
diff --git a/configs/orangepi_pc_plus_defconfig b/configs/orangepi_pc_plus_defconfig
index ce26cfa..31e9bcf 100644
--- a/configs/orangepi_pc_plus_defconfig
+++ b/configs/orangepi_pc_plus_defconfig
@@ -3,8 +3,6 @@
 CONFIG_SPL=y
 CONFIG_MACH_SUN8I_H3=y
 CONFIG_DRAM_CLK=624
-CONFIG_DRAM_ZQ=3881979
-CONFIG_DRAM_ODT_EN=y
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 CONFIG_NR_DRAM_BANKS=1
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
diff --git a/configs/orangepi_plus2e_defconfig b/configs/orangepi_plus2e_defconfig
index b0813e4..f31fd28 100644
--- a/configs/orangepi_plus2e_defconfig
+++ b/configs/orangepi_plus2e_defconfig
@@ -3,8 +3,6 @@
 CONFIG_SPL=y
 CONFIG_MACH_SUN8I_H3=y
 CONFIG_DRAM_CLK=672
-CONFIG_DRAM_ZQ=3881979
-CONFIG_DRAM_ODT_EN=y
 CONFIG_MACPWR="PD6"
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 CONFIG_NR_DRAM_BANKS=1
diff --git a/configs/orangepi_plus_defconfig b/configs/orangepi_plus_defconfig
index 0502373..8a9ea27 100644
--- a/configs/orangepi_plus_defconfig
+++ b/configs/orangepi_plus_defconfig
@@ -3,8 +3,6 @@
 CONFIG_SPL=y
 CONFIG_MACH_SUN8I_H3=y
 CONFIG_DRAM_CLK=672
-CONFIG_DRAM_ZQ=3881979
-CONFIG_DRAM_ODT_EN=y
 CONFIG_MACPWR="PD6"
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 CONFIG_USB1_VBUS_PIN="PG13"
diff --git a/configs/orangepi_prime_defconfig b/configs/orangepi_prime_defconfig
index 20ae6df..0d64eeb 100644
--- a/configs/orangepi_prime_defconfig
+++ b/configs/orangepi_prime_defconfig
@@ -4,6 +4,7 @@
 CONFIG_MACH_SUN50I_H5=y
 CONFIG_DRAM_CLK=672
 CONFIG_DRAM_ZQ=3881977
+# CONFIG_DRAM_ODT_EN is not set
 CONFIG_NR_DRAM_BANKS=1
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 # CONFIG_CMD_FLASH is not set
diff --git a/configs/orangepi_r1_defconfig b/configs/orangepi_r1_defconfig
index 05c3b08..6492d85 100644
--- a/configs/orangepi_r1_defconfig
+++ b/configs/orangepi_r1_defconfig
@@ -3,8 +3,6 @@
 CONFIG_SPL=y
 CONFIG_MACH_SUN8I_H3=y
 CONFIG_DRAM_CLK=624
-CONFIG_DRAM_ZQ=3881979
-CONFIG_DRAM_ODT_EN=y
 # CONFIG_VIDEO_DE2 is not set
 CONFIG_SPL_SPI_SUNXI=y
 CONFIG_NR_DRAM_BANKS=1
diff --git a/configs/orangepi_zero_defconfig b/configs/orangepi_zero_defconfig
index 44fc18b..b881a84 100644
--- a/configs/orangepi_zero_defconfig
+++ b/configs/orangepi_zero_defconfig
@@ -3,8 +3,6 @@
 CONFIG_SPL=y
 CONFIG_MACH_SUN8I_H3=y
 CONFIG_DRAM_CLK=624
-CONFIG_DRAM_ZQ=3881979
-CONFIG_DRAM_ODT_EN=y
 # CONFIG_VIDEO_DE2 is not set
 CONFIG_SPL_SPI_SUNXI=y
 CONFIG_NR_DRAM_BANKS=1
diff --git a/configs/orangepi_zero_plus2_defconfig b/configs/orangepi_zero_plus2_defconfig
index e62b3cb..ab0d12e 100644
--- a/configs/orangepi_zero_plus2_defconfig
+++ b/configs/orangepi_zero_plus2_defconfig
@@ -4,6 +4,7 @@
 CONFIG_MACH_SUN50I_H5=y
 CONFIG_DRAM_CLK=672
 CONFIG_DRAM_ZQ=3881977
+# CONFIG_DRAM_ODT_EN is not set
 CONFIG_MMC0_CD_PIN="PH13"
 CONFIG_MMC_SUNXI_SLOT_EXTRA=2
 CONFIG_NR_DRAM_BANKS=1
diff --git a/configs/orangepi_zero_plus_defconfig b/configs/orangepi_zero_plus_defconfig
index cc8b8c7..37ca6df 100644
--- a/configs/orangepi_zero_plus_defconfig
+++ b/configs/orangepi_zero_plus_defconfig
@@ -4,6 +4,7 @@
 CONFIG_MACH_SUN50I_H5=y
 CONFIG_DRAM_CLK=624
 CONFIG_DRAM_ZQ=3881977
+# CONFIG_DRAM_ODT_EN is not set
 CONFIG_NR_DRAM_BANKS=1
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 # CONFIG_CMD_FLASH is not set
diff --git a/configs/pine64-lts_defconfig b/configs/pine64-lts_defconfig
index fd3cdee..a833137 100644
--- a/configs/pine64-lts_defconfig
+++ b/configs/pine64-lts_defconfig
@@ -16,4 +16,5 @@
 CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-pine64-lts"
 CONFIG_SUN8I_EMAC=y
 CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig
index da4bdce..c04ecd9 100644
--- a/configs/sandbox64_defconfig
+++ b/configs/sandbox64_defconfig
@@ -194,6 +194,7 @@
 CONFIG_TPM=y
 CONFIG_LZ4=y
 CONFIG_ERRNO_STR=y
+CONFIG_TEST_FDTDEC=y
 CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 193e418..bb508a8 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -215,6 +215,7 @@
 CONFIG_TPM=y
 CONFIG_LZ4=y
 CONFIG_ERRNO_STR=y
+CONFIG_TEST_FDTDEC=y
 CONFIG_UNIT_TEST=y
 CONFIG_UT_TIME=y
 CONFIG_UT_DM=y
diff --git a/configs/sheevaplug_defconfig b/configs/sheevaplug_defconfig
index 04b00cd..ec527fc 100644
--- a/configs/sheevaplug_defconfig
+++ b/configs/sheevaplug_defconfig
@@ -39,6 +39,7 @@
 CONFIG_RTC_MV=y
 CONFIG_SYS_NS16550=y
 CONFIG_USB=y
+CONFIG_DM_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
 CONFIG_LZMA=y
diff --git a/configs/stm32mp15_basic_defconfig b/configs/stm32mp15_basic_defconfig
index d20b2ab..6781adb 100644
--- a/configs/stm32mp15_basic_defconfig
+++ b/configs/stm32mp15_basic_defconfig
@@ -1,11 +1,12 @@
 CONFIG_ARM=y
 CONFIG_ARCH_STM32MP=y
-CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_SYS_MALLOC_F_LEN=0x3000
 CONFIG_SPL_MMC_SUPPORT=y
 CONFIG_SPL=y
 CONFIG_TARGET_STM32MP1=y
 CONFIG_DISTRO_DEFAULTS=y
-CONFIG_NR_DRAM_BANKS=1
+CONFIG_FIT=y
+CONFIG_BOOTCOMMAND="run bootcmd_stm32mp"
 CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION=y
 CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION=3
 CONFIG_SPL_I2C_SUPPORT=y
@@ -18,8 +19,10 @@
 # CONFIG_CMD_EXPORTENV is not set
 # CONFIG_CMD_IMPORTENV is not set
 CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_MEMTEST=y
 CONFIG_CMD_ADC=y
 CONFIG_CMD_CLK=y
+CONFIG_CMD_DFU=y
 CONFIG_CMD_FUSE=y
 CONFIG_CMD_GPIO=y
 CONFIG_CMD_GPT=y
@@ -27,12 +30,21 @@
 CONFIG_CMD_MMC=y
 CONFIG_CMD_USB=y
 CONFIG_CMD_USB_MASS_STORAGE=y
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_TIME=y
+CONFIG_CMD_TIMER=y
 CONFIG_CMD_PMIC=y
 CONFIG_CMD_REGULATOR=y
 CONFIG_CMD_EXT4_WRITE=y
 # CONFIG_SPL_DOS_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="stm32mp157c-ev1"
 CONFIG_STM32_ADC=y
+CONFIG_USB_FUNCTION_FASTBOOT=y
+CONFIG_FASTBOOT_BUF_ADDR=0xC0000000
+CONFIG_FASTBOOT_BUF_SIZE=0x02000000
+CONFIG_FASTBOOT_USB_DEV=1
+CONFIG_FASTBOOT_FLASH=y
+CONFIG_FASTBOOT_FLASH_MMC_DEV=1
 CONFIG_DM_HWSPINLOCK=y
 CONFIG_HWSPINLOCK_STM32=y
 CONFIG_DM_I2C=y
@@ -43,15 +55,16 @@
 CONFIG_STM32_SDMMC2=y
 CONFIG_PHY=y
 CONFIG_PHY_STM32_USBPHYC=y
-# CONFIG_PINCTRL_FULL is not set
+CONFIG_PINCONF=y
 # CONFIG_SPL_PINCTRL_FULL is not set
+CONFIG_PINCTRL_STMFX=y
 CONFIG_DM_PMIC=y
 # CONFIG_SPL_PMIC_CHILDREN is not set
-CONFIG_PMIC_STPMU1=y
+CONFIG_PMIC_STPMIC1=y
 CONFIG_DM_REGULATOR_FIXED=y
 CONFIG_DM_REGULATOR_GPIO=y
 CONFIG_DM_REGULATOR_STM32_VREFBUF=y
-CONFIG_DM_REGULATOR_STPMU1=y
+CONFIG_DM_REGULATOR_STPMIC1=y
 CONFIG_SERIAL_RX_BUFFER=y
 CONFIG_STM32_SERIAL=y
 CONFIG_USB=y
@@ -64,4 +77,3 @@
 CONFIG_USB_GADGET_VENDOR_NUM=0x0483
 CONFIG_USB_GADGET_PRODUCT_NUM=0x5720
 CONFIG_USB_GADGET_DWC2_OTG=y
-CONFIG_USB_GADGET_DOWNLOAD=y
diff --git a/configs/stm32mp15_trusted_defconfig b/configs/stm32mp15_trusted_defconfig
new file mode 100644
index 0000000..a050cee
--- /dev/null
+++ b/configs/stm32mp15_trusted_defconfig
@@ -0,0 +1,70 @@
+CONFIG_ARM=y
+CONFIG_ARCH_STM32MP=y
+CONFIG_SYS_MALLOC_F_LEN=0x3000
+CONFIG_TARGET_STM32MP1=y
+CONFIG_DISTRO_DEFAULTS=y
+CONFIG_FIT=y
+CONFIG_BOOTCOMMAND="run bootcmd_stm32mp"
+CONFIG_SYS_PROMPT="STM32MP> "
+# CONFIG_CMD_BOOTD is not set
+# CONFIG_CMD_ELF is not set
+# CONFIG_CMD_IMI is not set
+# CONFIG_CMD_XIMG is not set
+# CONFIG_CMD_EXPORTENV is not set
+# CONFIG_CMD_IMPORTENV is not set
+CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_MEMTEST=y
+CONFIG_CMD_ADC=y
+CONFIG_CMD_CLK=y
+CONFIG_CMD_DFU=y
+CONFIG_CMD_FUSE=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_GPT=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_USB=y
+CONFIG_CMD_USB_MASS_STORAGE=y
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_TIME=y
+CONFIG_CMD_TIMER=y
+CONFIG_CMD_PMIC=y
+CONFIG_CMD_REGULATOR=y
+CONFIG_CMD_EXT4_WRITE=y
+CONFIG_DEFAULT_DEVICE_TREE="stm32mp157c-ev1"
+CONFIG_STM32_ADC=y
+CONFIG_USB_FUNCTION_FASTBOOT=y
+CONFIG_FASTBOOT_BUF_ADDR=0xC0000000
+CONFIG_FASTBOOT_BUF_SIZE=0x02000000
+CONFIG_FASTBOOT_USB_DEV=1
+CONFIG_FASTBOOT_FLASH=y
+CONFIG_FASTBOOT_FLASH_MMC_DEV=1
+CONFIG_DM_HWSPINLOCK=y
+CONFIG_HWSPINLOCK_STM32=y
+CONFIG_DM_I2C=y
+CONFIG_SYS_I2C_STM32F7=y
+CONFIG_LED=y
+CONFIG_LED_GPIO=y
+CONFIG_DM_MMC=y
+CONFIG_STM32_SDMMC2=y
+CONFIG_PHY=y
+CONFIG_PHY_STM32_USBPHYC=y
+CONFIG_PINCONF=y
+CONFIG_PINCTRL_STMFX=y
+CONFIG_DM_PMIC=y
+CONFIG_PMIC_STPMIC1=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_DM_REGULATOR_GPIO=y
+CONFIG_DM_REGULATOR_STM32_VREFBUF=y
+CONFIG_DM_REGULATOR_STPMIC1=y
+CONFIG_SERIAL_RX_BUFFER=y
+CONFIG_STM32_SERIAL=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_GENERIC=y
+CONFIG_USB_DWC2=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="STMicroelectronics"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0483
+CONFIG_USB_GADGET_PRODUCT_NUM=0x5720
+CONFIG_USB_GADGET_DWC2_OTG=y
diff --git a/configs/theadorable_debug_defconfig b/configs/theadorable_debug_defconfig
index fb9307a..3736aec 100644
--- a/configs/theadorable_debug_defconfig
+++ b/configs/theadorable_debug_defconfig
@@ -51,6 +51,7 @@
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_SPL_OF_TRANSLATE=y
 CONFIG_SATA_MV=y
+CONFIG_BLK=y
 CONFIG_BOOTCOUNT_LIMIT=y
 CONFIG_BOOTCOUNT_RAM=y
 CONFIG_FPGA_ALTERA=y
diff --git a/configs/turris_omnia_defconfig b/configs/turris_omnia_defconfig
index c406b25..85f2141 100644
--- a/configs/turris_omnia_defconfig
+++ b/configs/turris_omnia_defconfig
@@ -43,6 +43,7 @@
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_MV=y
 CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_SPANSION=y
 CONFIG_PHY_MARVELL=y
 CONFIG_PHY_GIGE=y
 CONFIG_MVNETA=y
diff --git a/configs/x530_defconfig b/configs/x530_defconfig
index cd18e9e..c893c44 100644
--- a/configs/x530_defconfig
+++ b/configs/x530_defconfig
@@ -19,6 +19,8 @@
 CONFIG_SILENT_U_BOOT_ONLY=y
 CONFIG_SILENT_CONSOLE_UPDATE_ON_RELOC=y
 CONFIG_MISC_INIT_R=y
+CONFIG_SPL_BOARD_INIT=y
+CONFIG_SPL_WATCHDOG_SUPPORT=y
 CONFIG_CMD_MEMINFO=y
 # CONFIG_CMD_FLASH is not set
 CONFIG_CMD_GPIO=y
@@ -72,3 +74,6 @@
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_ETHER_ASIX=y
 CONFIG_USB_ETHER_ASIX88179=y
+CONFIG_WATCHDOG=y
+CONFIG_WDT=y
+CONFIG_WDT_ORION=y
diff --git a/doc/README.chromium b/doc/README.chromium
index 45eaece..096bc4f 100644
--- a/doc/README.chromium
+++ b/doc/README.chromium
@@ -1,239 +1,177 @@
-Running U-Boot from coreboot on Chromebooks
-===========================================
+Chromium OS Support in U-Boot
+=============================
 
-U-Boot can be used as a secondary boot loader in a few situations such as from
-UEFI and coreboot (see README.x86). Recent Chromebooks use coreboot even on
-ARM platforms to start up the machine.
+Introduction
+------------
 
-This document aims to provide a guide to booting U-Boot on a Chromebook. It
-is only a starting point, and there are many guides on the interwebs. But
-placing this information in the U-Boot tree should make it easier to find for
-those who use U-Boot habitually.
+This describes how to use U-Boot with Chromium OS. Several options are
+available:
 
-Most of these platforms are supported by U-Boot natively, but it is risky to
-replace the ROM unless you have a servo board and cable to restore it with.
+   - Running U-Boot from the 'altfw' feature, which is available on selected
+        Chromebooks from 2019 onwards (initially Grunt). Press '1' from the
+        developer-mode screen to get into U-Boot. See here for details:
+        https://sites.google.com/a/chromium.org/dev/chromium-os/poking-around-your-chrome-os-device?pli=1
 
+   - Running U-Boot from the disk partition. This involves signing U-Boot and
+        placing it on the disk, for booting as a 'kernel'. See
+        README.chromium-chainload for information on this. This is the only
+        option on non-U-Boot Chromebooks from 2013 to 2018 and is somewhat
+        more involved.
 
-For all of these the standard U-Boot build instructions apply. For example on
-ARM:
+   - Running U-Boot with Chromium OS verified boot. This allows U-Boot to be
+        used instead of either or both of depthcharge (a bootloader which forked
+        from U-Boot in 2013) and coreboot. See below for more information on
+        this.
 
-   sudo apt install gcc-arm-linux-gnueabi
-   mkdir b
-   make O=b/nyan_big CROSS_COMPILE=arm-linux-gnueabi- nyan-big_defconfig all
 
-You can obtain the vbutil_kernel utility here:
+U-Boot with Chromium OS verified boot
+-------------------------------------
 
-   https://drive.google.com/open?id=0B7WYZbZ9zd-3dHlVVXo4VXE2T0U
+To obtain:
 
+   git clone https://github.com/sglass68/u-boot.git
+   cd u-boot
+   git checkout cros-master
 
-Snow (Samsung ARM Chromebook)
------------------------------
+To build for sandbox:
 
-See here:
+   UB=/tmp/b/chromeos_sandbox    # U-Boot build directory
+   CROS=/home/sglass/cosarm      # Chromium OS directory
+   make O=$UB/chromeos_sandbox_defconfig
+   make O=$UB -j20 -s VBOOT_SOURCE=$CROS/src/platform/vboot_reference \
+	MAKEFLAGS_VBOOT=DEBUG=1 QUIET=1
 
-https://www.chromium.org/chromium-os/firmware-porting-guide/using-nv-u-boot-on-the-samsung-arm-chromebook
+Replace sandbox with another supported target.
 
+This produces $UB/image.bin which contains the firmware binaries in a SPI
+flash image.
 
-Nyan-big
---------
-
-Compiled based on information here:
-https://lists.denx.de/pipermail/u-boot/2015-March/209530.html
-https://git.collabora.com/cgit/user/tomeu/u-boot.git/commit/?h=nyan-big
-https://lists.denx.de/pipermail/u-boot/2017-May/289491.html
-https://github.com/chromeos-nvidia-androidtv/gnu-linux-on-acer-chromebook-13#copy-data-to-the-sd-card
-
-1. Build U-Boot
-
-   mkdir b
-   make -j8 O=b/nyan-big CROSS_COMPILE=arm-linux-gnueabi- nyan-big_defconfig all
-
-
-2. Select a .its file
-
-Select something from doc/chromium which matches your board, or create your
-own.
-
-Note that the device tree node is required, even though it is not actually
-used by U-Boot. This is because the Chromebook expects to pass it to the
-kernel, and crashes if it is not present.
-
-
-3. Build and sign an image
-
-   ./b/nyan-big/tools/mkimage -f doc/chromium/nyan-big.its u-boot-chromium.fit
-   echo test >dummy.txt
-   vbutil_kernel --arch arm --keyblock doc/chromium/devkeys/kernel.keyblock \
-	--signprivate doc/chromium/devkeys/kernel_data_key.vbprivk \
-	--version 1 --config dummy.txt --vmlinuz u-boot-chromium.fit \
-	--bootloader dummy.txt --pack u-boot.kpart
-
-
-4. Prepare an SD card
-
-   DISK=/dev/sdc   # Replace with your actual SD card device
-   sudo cgpt create $DISK
-   sudo cgpt add -b 34 -s 32768 -P 1 -S 1 -t kernel $DISK
-   sudo cgpt add -b 32802 -s 2000000 -t rootfs $DISK
-   sudo gdisk $DISK   # Enter command 'w' to write a protective MBR to the disk
-
-
-5. Write U-Boot to the SD card
-
-   sudo dd if=u-boot.kpart of=/dev/sdc1; sync
+To run on sandbox:
 
+   $UB/tpl/u-boot-tpl -d $UB/u-boot.dtb.out \
+	-L6 -c "host bind 0 $CROS/src/build/images/cheza/latest/chromiumos_image.bin; vboot go auto" \
+	-l -w -s state.dtb -r
 
-6. Start it up
+To run on other boards:
+   Install image.bin in the SPI flash of your device
+   Boot your system
 
-Reboot the device in dev mode. Make sure that you have USB booting enabled. To
-do this, login as root (via Ctrl-Alt-forward_arrow) and type
-'enable_dev_usb_boot'. You only need to do this once.
 
-Reboot the device with the SD card inserted. Press Clrl-U at the developer
-mode screen. It should show something like the following on the display:
+Sandbox
+-------
 
-   U-Boot 2017.07-00637-g242eb42-dirty (May 22 2017 - 06:14:21 -0600)
+Most Chromium OS development with U-Boot is undertaken using sandbox. There is
+a sandbox target available (chromeos_sandbox) which allows running U-Boot on
+a Linux machine completion with emulations of the display, TPM, disk, etc.
 
-   Model: Acer Chromebook 13 CB5-311
-   Board: Google/NVIDIA Nyan-big, ID: 1
+Running sandbox starts TPL, which contains the first phase of vboot, providing
+a device tree and binding a Chromium OS disk image for use to find kernels
+(any Chromium OS image will do). It also saves driver state between U-Boot
+phases into state.dtb and will automatically ensure that memory is shared
+between all phases. TPL will jump to SPL and then on to U-Boot proper.
 
-   Net:   No ethernet found.
-   Hit any key to stop autoboot:  0
-   Tegra124 (Nyan-big) #
+It is possible to run with debugging on, e.g.
 
+   gdb --args $UB/tpl/u-boot-tpl -d ....
 
-7. Known problems
+Breakpoints can be set in any U-Boot phase. Overall this is a good debugging
+environment for new verified-boot features.
 
-On the serial console the word MMC is chopped at the start of the line:
 
-C:   sdhci@700b0000: 2, sdhci@700b0400: 1, sdhci@700b0600: 0
+Samus
+-----
 
-This is likely due to some problem with change-over of the serial driver
-during relocation (or perhaps updating the clock setup in board_init()).
+Basic support is available for samus, using the chromeos_samus target. If you
+have an em100, use:
 
+   sudo em100 -s -c W25Q128FW -d $UB/image.bin -t -r
 
-9. Notes
+to write the image and then boot samus (Power-Refresh).
 
-To check that you copied the u-boot.its file correctly, use these commands.
-You should see that the data at 0x100 in u-boot-chromium.fit is the first few
-bytes of U-Boot:
 
-   hd u-boot-chromium.fit |head -20
-   ...
-   00000100  b8 00 00 ea 14 f0 9f e5  14 f0 9f e5 14 f0 9f e5  |................|
+Boot flow
+---------
 
-   hd b/nyan-big/u-boot.bin |head
-   00000000  b8 00 00 ea 14 f0 9f e5  14 f0 9f e5 14 f0 9f e5  |................|
+Verified boot starts in TPL, which selects the A or B SPL, which in turn selects
+the A or B U-Boot. Then this jumps to the selected kernel. If anything goes
+wrong, the device reboots and the recovery SPL and U-Boot are used instead.
 
+More details are available here:
 
-The 'data' property of the FIT is set up to start at offset 0x100 bytes into
-the file. The change to CONFIG_SYS_TEXT_BASE is also an offset of 0x100 bytes
-from the load address. If this changes, you either need to modify U-Boot to be
-fully relocatable, or expect it to hang.
+   https://www.chromium.org/chromium-os/chromiumos-design-docs/firmware-boot-and-recovery
 
 
-chromebook_jerry
-----------------
+New uclasses
+------------
 
-The instruction are similar to those for Nyan with changes as noted below:
+Several uclasses are provided in cros/:
 
-1. Patch U-Boot
+	UCLASS_CROS_AUX_FW		Chrome OS auxiliary firmware
+	UCLASS_CROS_FWSTORE		Chrome OS firmware storage
+	UCLASS_CROS_NVDATA		Chrome OS non-volatile data device
+	UCLASS_CROS_VBOOT_EC		Chrome OS vboot EC operations
+	UCLASS_CROS_VBOOT_FLAG		Chrome OS verified boot flag
 
-Open include/configs/rk3288_common.h
+The existing UCLASS_CROS_EC is also used.
 
-Change:
 
-#define CONFIG_SYS_TEXT_BASE		0x00100000
-
-to:
-
-#define CONFIG_SYS_TEXT_BASE		0x02000100
-
-
-
-2. Build U-Boot
-
-   mkdir b
-   make -j8 O=b/chromebook_jerry CROSS_COMPILE=arm-linux-gnueabi- \
-	chromebook_jerry_defconfig all
-
-
-3. See above
-
-4. Build and sign an image
-
-   ./b/chromebook_jerry/tools/mkimage -f doc/chromium/chromebook_jerry.its \
-	u-boot-chromium.fit
-   echo test >dummy.txt
-   vbutil_kernel --arch arm --keyblock doc/chromium/devkeys/kernel.keyblock \
-	--signprivate doc/chromium/devkeys/kernel_data_key.vbprivk \
-	--version 1 --config dummy.txt --vmlinuz u-boot-chromium.fit \
-	--bootloader dummy.txt --pack u-boot.kpart
-
-
-5. See above
-
-6. See above
-
-7. Start it up
+Commands
+--------
 
-Reboot the device in dev mode. Make sure that you have USB booting enabled. To
-do this, login as root (via Ctrl-Alt-forward_arrow) and type
-'enable_dev_usb_boot'. You only need to do this once.
+A new 'vboot' command is provided to run particular vboot stages. The most
+useful command is 'vboot go auto', which continues where the last stage left
+off.
 
-Reboot the device with the SD card inserted. Press Clrl-U at the developer
-mode screen. It should show something like the following on the display:
+Note that TPL and SPL do not supports commands as yet, so the vboot code is
+called directly from the SPL boot devices (BOOT_DEVICE_CROS_VBOOT). See
+cros_load_image_tpl() and cros_load_image_spl() which both call
+vboot_run_auto().
 
-   U-Boot 2017.05-00649-g72acdbf-dirty (May 29 2017 - 14:57:05 -0600)
 
-   Model: Google Jerry
-   Net:   Net Initialization Skipped
-   No ethernet found.
-   Hit any key to stop autoboot:  0
+Config options
+--------------
 
+The main option is CONFIG_CHROMEOS, which enables a wide array of other options
+so that the required features are present.
 
-8. Known problems
 
-None as yet.
+Device-tree config
+------------------
 
+Various options are available which control the operation of verified boot.
+See cros/dts/bindings/config.txt for details. Most config is handled at run-
+time, although build-time config (with Kconfig) could also be added fairly
+easily.
 
-9. Notes
 
-None as yet.
+Porting to other hardware
+-------------------------
 
+A basic port to samus (Chromebook Pixel 2015) is in a basic working state,
+using the chromeos_samus target. Patches will likely be forthcoming in early
+2019. Ports to an ARM board and coreboot (for x86 Chromebooks) are in the
+dreaming state.
 
-Other notes
-===========
 
-flashrom
---------
+Tests
+-----
 
-   Used to make a backup of your firmware, or to replace it.
+Chromium OS firmware has a very limited set of tests. The tests that originally
+existed in U-Boot were not brought over to coreboot or depthcharge.
 
-   See: https://www.chromium.org/chromium-os/packages/cros-flashrom
+The U-Boot tests ('make check') do operate, but at present there are no
+Chromium OS tests available. These will hopefully come together over time. Of
+course the above sandbox feature provides a sort of functional test and can
+detecte problems that affect the flow or particular vboot features.
 
 
-coreboot
---------
+TO DO
+-----
 
-Coreboot itself is not designed to actually boot an OS. Instead, a program
-called Depthcharge is used. This originally came out of U-Boot and was then
-heavily hacked and modified such that is is almost unrecognisable. It does
-include a very small part of the U-Boot command-line interface but is not
-usable as a general-purpose boot loader.
+- Support for booting from coreboot (patches expected March 2019)
+- Support for booting from an ARM board, e.g. bob
 
-In addition, it has a very unusual design in that it does not do device init
-itself, but instead relies on coreboot. This is similar to (in U-Boot) having
-a SPI driver with an empty probe() method, relying on whatever was set up
-beforehand. It can be quite hard to figure out between these two code bases
-what settings are actually used. When chain-loading into U-Boot we must be
-careful to reinit anything that U-Boot expects. If not, some peripherals (or
-the whole machine) may not work. This makes the process of chainloading more
-complicated than it could be on some platforms.
 
-Finally, it supports only a subset of the U-Boot's FIT format. In particular
-it uses a fixed address to load the FIT and does not support load/exec
-addresses. This means that U-Boot must be able to boot from whatever
-address Depthcharge happens to use (it is the CONFIG_KERNEL_START setting
-in Depthcharge). In practice this means that the data in the kernel@1 FIT node
-(see above) must start at the same address as U-Boot's CONFIG_SYS_TEXT_BASE.
+Simon Glass
+sjg@chromium.org
+7 October 2018
diff --git a/doc/README.chromium-chainload b/doc/README.chromium-chainload
new file mode 100644
index 0000000..45eaece
--- /dev/null
+++ b/doc/README.chromium-chainload
@@ -0,0 +1,239 @@
+Running U-Boot from coreboot on Chromebooks
+===========================================
+
+U-Boot can be used as a secondary boot loader in a few situations such as from
+UEFI and coreboot (see README.x86). Recent Chromebooks use coreboot even on
+ARM platforms to start up the machine.
+
+This document aims to provide a guide to booting U-Boot on a Chromebook. It
+is only a starting point, and there are many guides on the interwebs. But
+placing this information in the U-Boot tree should make it easier to find for
+those who use U-Boot habitually.
+
+Most of these platforms are supported by U-Boot natively, but it is risky to
+replace the ROM unless you have a servo board and cable to restore it with.
+
+
+For all of these the standard U-Boot build instructions apply. For example on
+ARM:
+
+   sudo apt install gcc-arm-linux-gnueabi
+   mkdir b
+   make O=b/nyan_big CROSS_COMPILE=arm-linux-gnueabi- nyan-big_defconfig all
+
+You can obtain the vbutil_kernel utility here:
+
+   https://drive.google.com/open?id=0B7WYZbZ9zd-3dHlVVXo4VXE2T0U
+
+
+Snow (Samsung ARM Chromebook)
+-----------------------------
+
+See here:
+
+https://www.chromium.org/chromium-os/firmware-porting-guide/using-nv-u-boot-on-the-samsung-arm-chromebook
+
+
+Nyan-big
+--------
+
+Compiled based on information here:
+https://lists.denx.de/pipermail/u-boot/2015-March/209530.html
+https://git.collabora.com/cgit/user/tomeu/u-boot.git/commit/?h=nyan-big
+https://lists.denx.de/pipermail/u-boot/2017-May/289491.html
+https://github.com/chromeos-nvidia-androidtv/gnu-linux-on-acer-chromebook-13#copy-data-to-the-sd-card
+
+1. Build U-Boot
+
+   mkdir b
+   make -j8 O=b/nyan-big CROSS_COMPILE=arm-linux-gnueabi- nyan-big_defconfig all
+
+
+2. Select a .its file
+
+Select something from doc/chromium which matches your board, or create your
+own.
+
+Note that the device tree node is required, even though it is not actually
+used by U-Boot. This is because the Chromebook expects to pass it to the
+kernel, and crashes if it is not present.
+
+
+3. Build and sign an image
+
+   ./b/nyan-big/tools/mkimage -f doc/chromium/nyan-big.its u-boot-chromium.fit
+   echo test >dummy.txt
+   vbutil_kernel --arch arm --keyblock doc/chromium/devkeys/kernel.keyblock \
+	--signprivate doc/chromium/devkeys/kernel_data_key.vbprivk \
+	--version 1 --config dummy.txt --vmlinuz u-boot-chromium.fit \
+	--bootloader dummy.txt --pack u-boot.kpart
+
+
+4. Prepare an SD card
+
+   DISK=/dev/sdc   # Replace with your actual SD card device
+   sudo cgpt create $DISK
+   sudo cgpt add -b 34 -s 32768 -P 1 -S 1 -t kernel $DISK
+   sudo cgpt add -b 32802 -s 2000000 -t rootfs $DISK
+   sudo gdisk $DISK   # Enter command 'w' to write a protective MBR to the disk
+
+
+5. Write U-Boot to the SD card
+
+   sudo dd if=u-boot.kpart of=/dev/sdc1; sync
+
+
+6. Start it up
+
+Reboot the device in dev mode. Make sure that you have USB booting enabled. To
+do this, login as root (via Ctrl-Alt-forward_arrow) and type
+'enable_dev_usb_boot'. You only need to do this once.
+
+Reboot the device with the SD card inserted. Press Clrl-U at the developer
+mode screen. It should show something like the following on the display:
+
+   U-Boot 2017.07-00637-g242eb42-dirty (May 22 2017 - 06:14:21 -0600)
+
+   Model: Acer Chromebook 13 CB5-311
+   Board: Google/NVIDIA Nyan-big, ID: 1
+
+   Net:   No ethernet found.
+   Hit any key to stop autoboot:  0
+   Tegra124 (Nyan-big) #
+
+
+7. Known problems
+
+On the serial console the word MMC is chopped at the start of the line:
+
+C:   sdhci@700b0000: 2, sdhci@700b0400: 1, sdhci@700b0600: 0
+
+This is likely due to some problem with change-over of the serial driver
+during relocation (or perhaps updating the clock setup in board_init()).
+
+
+9. Notes
+
+To check that you copied the u-boot.its file correctly, use these commands.
+You should see that the data at 0x100 in u-boot-chromium.fit is the first few
+bytes of U-Boot:
+
+   hd u-boot-chromium.fit |head -20
+   ...
+   00000100  b8 00 00 ea 14 f0 9f e5  14 f0 9f e5 14 f0 9f e5  |................|
+
+   hd b/nyan-big/u-boot.bin |head
+   00000000  b8 00 00 ea 14 f0 9f e5  14 f0 9f e5 14 f0 9f e5  |................|
+
+
+The 'data' property of the FIT is set up to start at offset 0x100 bytes into
+the file. The change to CONFIG_SYS_TEXT_BASE is also an offset of 0x100 bytes
+from the load address. If this changes, you either need to modify U-Boot to be
+fully relocatable, or expect it to hang.
+
+
+chromebook_jerry
+----------------
+
+The instruction are similar to those for Nyan with changes as noted below:
+
+1. Patch U-Boot
+
+Open include/configs/rk3288_common.h
+
+Change:
+
+#define CONFIG_SYS_TEXT_BASE		0x00100000
+
+to:
+
+#define CONFIG_SYS_TEXT_BASE		0x02000100
+
+
+
+2. Build U-Boot
+
+   mkdir b
+   make -j8 O=b/chromebook_jerry CROSS_COMPILE=arm-linux-gnueabi- \
+	chromebook_jerry_defconfig all
+
+
+3. See above
+
+4. Build and sign an image
+
+   ./b/chromebook_jerry/tools/mkimage -f doc/chromium/chromebook_jerry.its \
+	u-boot-chromium.fit
+   echo test >dummy.txt
+   vbutil_kernel --arch arm --keyblock doc/chromium/devkeys/kernel.keyblock \
+	--signprivate doc/chromium/devkeys/kernel_data_key.vbprivk \
+	--version 1 --config dummy.txt --vmlinuz u-boot-chromium.fit \
+	--bootloader dummy.txt --pack u-boot.kpart
+
+
+5. See above
+
+6. See above
+
+7. Start it up
+
+Reboot the device in dev mode. Make sure that you have USB booting enabled. To
+do this, login as root (via Ctrl-Alt-forward_arrow) and type
+'enable_dev_usb_boot'. You only need to do this once.
+
+Reboot the device with the SD card inserted. Press Clrl-U at the developer
+mode screen. It should show something like the following on the display:
+
+   U-Boot 2017.05-00649-g72acdbf-dirty (May 29 2017 - 14:57:05 -0600)
+
+   Model: Google Jerry
+   Net:   Net Initialization Skipped
+   No ethernet found.
+   Hit any key to stop autoboot:  0
+
+
+8. Known problems
+
+None as yet.
+
+
+9. Notes
+
+None as yet.
+
+
+Other notes
+===========
+
+flashrom
+--------
+
+   Used to make a backup of your firmware, or to replace it.
+
+   See: https://www.chromium.org/chromium-os/packages/cros-flashrom
+
+
+coreboot
+--------
+
+Coreboot itself is not designed to actually boot an OS. Instead, a program
+called Depthcharge is used. This originally came out of U-Boot and was then
+heavily hacked and modified such that is is almost unrecognisable. It does
+include a very small part of the U-Boot command-line interface but is not
+usable as a general-purpose boot loader.
+
+In addition, it has a very unusual design in that it does not do device init
+itself, but instead relies on coreboot. This is similar to (in U-Boot) having
+a SPI driver with an empty probe() method, relying on whatever was set up
+beforehand. It can be quite hard to figure out between these two code bases
+what settings are actually used. When chain-loading into U-Boot we must be
+careful to reinit anything that U-Boot expects. If not, some peripherals (or
+the whole machine) may not work. This makes the process of chainloading more
+complicated than it could be on some platforms.
+
+Finally, it supports only a subset of the U-Boot's FIT format. In particular
+it uses a fixed address to load the FIT and does not support load/exec
+addresses. This means that U-Boot must be able to boot from whatever
+address Depthcharge happens to use (it is the CONFIG_KERNEL_START setting
+in Depthcharge). In practice this means that the data in the kernel@1 FIT node
+(see above) must start at the same address as U-Boot's CONFIG_SYS_TEXT_BASE.
diff --git a/doc/device-tree-bindings/i2c/i2c.txt b/doc/device-tree-bindings/i2c/i2c.txt
index de818d4..9698e48 100644
--- a/doc/device-tree-bindings/i2c/i2c.txt
+++ b/doc/device-tree-bindings/i2c/i2c.txt
@@ -12,6 +12,10 @@
 Optional properties:
 - u-boot,i2c-offset-len - length of chip offset in bytes. If omitted the
     default value of 1 is used.
+- u-boot,i2c-transaction-bytes - the length of single I2C transaction on
+    the bus. Some devices require more than single byte transmission
+    (e.g. mc34708 mfd). This information is necessary to correctly
+     initialize (put into idle state) I2C bus after soft reset.
 - gpios = <sda ...>, <scl ...>;
   pinctrl-names = "default", "gpio";
   pinctrl-0 = <&i2c_xfer>;
@@ -28,6 +32,7 @@
 		compatible = "google,cros-ec";
 		i2c-max-frequency = <100000>;
 		u-boot,i2c-offset-len = <0>;
+		u-boot,i2c-transaction-bytes = <3>;
 		ec-interrupt = <&gpx1 6 GPIO_ACTIVE_LOW>;
 	};
 };
diff --git a/doc/device-tree-bindings/mtd/stm32-fmc2-nand.txt b/doc/device-tree-bindings/mtd/stm32-fmc2-nand.txt
new file mode 100644
index 0000000..70e76be
--- /dev/null
+++ b/doc/device-tree-bindings/mtd/stm32-fmc2-nand.txt
@@ -0,0 +1,59 @@
+STMicroelectronics Flexible Memory Controller 2 (FMC2)
+NAND Interface
+
+Required properties:
+- compatible: Should be one of:
+              * st,stm32mp15-fmc2
+- reg: NAND flash controller memory areas.
+       First region contains the register location.
+       Regions 2 to 4 respectively contain the data, command,
+       and address space for CS0.
+       Regions 5 to 7 contain the same areas for CS1.
+- interrupts: The interrupt number
+- pinctrl-0: Standard Pinctrl phandle (see: pinctrl/pinctrl-bindings.txt)
+- clocks: The clock needed by the NAND flash controller
+
+Optional properties:
+- resets: Reference to a reset controller asserting the FMC controller
+- dmas: DMA specifiers (see: dma/stm32-mdma.txt)
+- dma-names: Must be "tx", "rx" and "ecc"
+
+Optional children nodes:
+Children nodes represent the available NAND chips.
+
+Optional properties:
+- nand-on-flash-bbt: see nand.txt
+- nand-ecc-strength: see nand.txt
+- nand-ecc-step-size: see nand.txt
+
+The following ECC strength and step size are currently supported:
+ - nand-ecc-strength = <1>, nand-ecc-step-size = <512> (Hamming)
+ - nand-ecc-strength = <4>, nand-ecc-step-size = <512> (BCH4)
+ - nand-ecc-strength = <8>, nand-ecc-step-size = <512> (BCH8) (default)
+
+Example:
+
+	fmc: nand-controller@58002000 {
+		compatible = "st,stm32mp15-fmc2";
+		reg = <0x58002000 0x1000>,
+		      <0x80000000 0x1000>,
+		      <0x88010000 0x1000>,
+		      <0x88020000 0x1000>,
+		      <0x81000000 0x1000>,
+		      <0x89010000 0x1000>,
+		      <0x89020000 0x1000>;
+		interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&rcc FMC_K>;
+		resets = <&rcc FMC_R>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&fmc_pins_a>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		nand@0 {
+			reg = <0>;
+			nand-on-flash-bbt;
+			#address-cells = <1>;
+			#size-cells = <1>;
+		};
+	};
diff --git a/doc/device-tree-bindings/pinctrl/atmel,at91-pio4-pinctrl.txt b/doc/device-tree-bindings/pinctrl/atmel,at91-pio4-pinctrl.txt
index a1b5596..a376c6f 100644
--- a/doc/device-tree-bindings/pinctrl/atmel,at91-pio4-pinctrl.txt
+++ b/doc/device-tree-bindings/pinctrl/atmel,at91-pio4-pinctrl.txt
@@ -42,7 +42,7 @@
 		status = "okay";
 
 		spi_flash@0 {
-			compatible = "spi-flash";
+			compatible = "jedec,spi-nor";
 			reg = <0>;
 			spi-max-frequency = <50000000>;
 		};
diff --git a/doc/device-tree-bindings/spi/spi-atcspi200.txt b/doc/device-tree-bindings/spi/spi-atcspi200.txt
index 9c0630b..e67b342 100644
--- a/doc/device-tree-bindings/spi/spi-atcspi200.txt
+++ b/doc/device-tree-bindings/spi/spi-atcspi200.txt
@@ -28,7 +28,7 @@
 		clocks = <&spiclk>;
 		interrupts = <3 4>;
 		flash@0 {
-			compatible = "spi-flash";
+			compatible = "jedec,spi-nor";
 			spi-max-frequency = <50000000>;
 			reg = <0>;
 			spi-cpol;
diff --git a/doc/device-tree-bindings/spi/spi-stm32-qspi.txt b/doc/device-tree-bindings/spi/spi-stm32-qspi.txt
index 6c7da1d..cec3e12 100644
--- a/doc/device-tree-bindings/spi/spi-stm32-qspi.txt
+++ b/doc/device-tree-bindings/spi/spi-stm32-qspi.txt
@@ -29,7 +29,7 @@
 		qflash0: n25q128a {
 			#address-cells = <1>;
 			#size-cells = <1>;
-			compatible = "micron,n25q128a13", "spi-flash";
+			compatible = "micron,n25q128a13", "jedec,spi-nor";
 			spi-max-frequency = <108000000>;
 			spi-tx-bus-width = <4>;
 			spi-rx-bus-width = <4>;
diff --git a/doc/git-mailrc b/doc/git-mailrc
index b75ebab..f989792 100644
--- a/doc/git-mailrc
+++ b/doc/git-mailrc
@@ -24,9 +24,8 @@
 alias hs             Heiko Schocher <hs@denx.de>
 alias iwamatsu       Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
 alias jaehoon        Jaehoon Chung <jh80.chung@samsung.com>
-alias jagan          Jagan Teki <jagan@openedev.com>
+alias jagan          Jagan Teki <jagan@amarulasolutions.com>
 alias jhersh         Joe Hershberger <joe.hershberger@ni.com>
-alias luka           Luka Perkov <luka.perkov@sartura.hr>
 alias lukma          Lukasz Majewski <lukma@denx.de>
 alias macpaul        Macpaul Lin <macpaul@andestech.com>
 alias marex          Marek Vasut <marex@denx.de>
@@ -35,7 +34,6 @@
 alias mateusz        Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
 alias maxime         Maxime Ripard <maxime.ripard@free-electrons.com>
 alias monstr         Michal Simek <monstr@monstr.eu>
-alias prafulla       Prafulla Wadaskar <prafulla@marvell.com>
 alias prom           Minkyu Kang <mk7.kang@samsung.com>
 alias ptomsich       Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
 alias sbabic         Stefano Babic <sbabic@denx.de>
@@ -56,7 +54,7 @@
 alias at91           uboot, abiessmann
 alias davinci        ti
 alias imx            uboot, sbabic
-alias kirkwood       uboot, prafulla, luka, stroese
+alias kirkwood       uboot, stroese
 alias omap           ti
 alias pxa            uboot, marex
 alias rmobile        uboot, iwamatsu
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 49a056e..7ebee75 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -81,7 +81,9 @@
 
 config SATA_MV
 	bool "Enable Marvell SATA controller driver support"
+	select AHCI
 	select LIBATA
+	depends on BLK
 	help
 	  Enable this driver to support the SATA controller found in
 	  some Marvell SoCs.
diff --git a/drivers/ata/ahci_mvebu.c b/drivers/ata/ahci_mvebu.c
index 6e3f17e..48a9d00 100644
--- a/drivers/ata/ahci_mvebu.c
+++ b/drivers/ata/ahci_mvebu.c
@@ -44,6 +44,7 @@
 }
 
 static const struct udevice_id mvebu_ahci_ids[] = {
+	{ .compatible = "marvell,armada-380-ahci" },
 	{ .compatible = "marvell,armada-3700-ahci" },
 	{ .compatible = "marvell,armada-8k-ahci" },
 	{ }
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index a168196..2a630d4 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -3,7 +3,7 @@
  * Copyright (C) Excito Elektronik i Skåne AB, 2010.
  * Author: Tor Krill <tor@excito.com>
  *
- * Copyright (C) 2015 Stefan Roese <sr@denx.de>
+ * Copyright (C) 2015, 2019 Stefan Roese <sr@denx.de>
  */
 
 /*
@@ -32,6 +32,10 @@
  */
 
 #include <common.h>
+#include <ahci.h>
+#include <dm.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
 #include <fis.h>
 #include <libata.h>
 #include <malloc.h>
@@ -40,11 +44,10 @@
 #include <asm/io.h>
 #include <linux/mbus.h>
 
+#include <asm/arch/soc.h>
 #if defined(CONFIG_KIRKWOOD)
-#include <asm/arch/kirkwood.h>
 #define SATAHC_BASE		KW_SATA_BASE
 #else
-#include <asm/arch/soc.h>
 #define SATAHC_BASE		MVEBU_AXP_SATA_BASE
 #endif
 
@@ -214,8 +217,8 @@
 #define CRQB_SECTCOUNT_COUNT_EXP_MASK	(0xff << 8)
 #define CRQB_SECTCOUNT_COUNT_EXP_SHIFT	8
 
-#define MVSATA_WIN_CONTROL(w)	(MVEBU_AXP_SATA_BASE + 0x30 + ((w) << 4))
-#define MVSATA_WIN_BASE(w)	(MVEBU_AXP_SATA_BASE + 0x34 + ((w) << 4))
+#define MVSATA_WIN_CONTROL(w)	(SATAHC_BASE + 0x30 + ((w) << 4))
+#define MVSATA_WIN_BASE(w)	(SATAHC_BASE + 0x34 + ((w) << 4))
 
 struct eprd {
 	u32 phyaddr_low;
@@ -256,6 +259,7 @@
 	u16 pio;
 	u16 mwdma;
 	u16 udma;
+	int dev_nr;
 
 	void *crqb_alloc;
 	struct crqb *request;
@@ -278,9 +282,9 @@
 }
 
 /* Cut from sata_mv in linux kernel */
-static int mv_stop_edma_engine(int port)
+static int mv_stop_edma_engine(struct udevice *dev, int port)
 {
-	struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
+	struct mv_priv *priv = dev_get_platdata(dev);
 	int i;
 
 	/* Disable eDMA. The disable bit auto clears. */
@@ -299,9 +303,9 @@
 	return -1;
 }
 
-static int mv_start_edma_engine(int port)
+static int mv_start_edma_engine(struct udevice *dev, int port)
 {
-	struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
+	struct mv_priv *priv = dev_get_platdata(dev);
 	u32 tmp;
 
 	/* Check preconditions */
@@ -351,12 +355,12 @@
 	return 0;
 }
 
-static int mv_reset_channel(int port)
+static int mv_reset_channel(struct udevice *dev, int port)
 {
-	struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
+	struct mv_priv *priv = dev_get_platdata(dev);
 
 	/* Make sure edma is stopped  */
-	mv_stop_edma_engine(port);
+	mv_stop_edma_engine(dev, port);
 
 	out_le32(priv->regbase + EDMA_CMD, EDMA_CMD_ATARST);
 	udelay(25);		/* allow reset propagation */
@@ -366,11 +370,11 @@
 	return 0;
 }
 
-static void mv_reset_port(int port)
+static void mv_reset_port(struct udevice *dev, int port)
 {
-	struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
+	struct mv_priv *priv = dev_get_platdata(dev);
 
-	mv_reset_channel(port);
+	mv_reset_channel(dev, port);
 
 	out_le32(priv->regbase + EDMA_CMD, 0x0);
 	out_le32(priv->regbase + EDMA_CFG, 0x101f);
@@ -392,9 +396,9 @@
 	out_le32(SATAHC_BASE + SATAHC_ICR, 0x00);
 }
 
-static int probe_port(int port)
+static int probe_port(struct udevice *dev, int port)
 {
-	struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
+	struct mv_priv *priv = dev_get_platdata(dev);
 	int tries, tries2, set15 = 0;
 	u32 tmp;
 
@@ -446,7 +450,7 @@
 			tmp &= ~SIR_CFG_GEN2EN;
 			out_le32(priv->regbase + SIR_ICFG, tmp);
 
-			mv_reset_channel(port);
+			mv_reset_channel(dev, port);
 		}
 	}
 
@@ -455,9 +459,9 @@
 }
 
 /* Get request queue in pointer */
-static int get_reqip(int port)
+static int get_reqip(struct udevice *dev, int port)
 {
-	struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
+	struct mv_priv *priv = dev_get_platdata(dev);
 	u32 tmp;
 
 	tmp = in_le32(priv->regbase + EDMA_RQIPR) & EDMA_RQIPR_IPMASK;
@@ -466,9 +470,9 @@
 	return tmp;
 }
 
-static void set_reqip(int port, int reqin)
+static void set_reqip(struct udevice *dev, int port, int reqin)
 {
-	struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
+	struct mv_priv *priv = dev_get_platdata(dev);
 	u32 tmp;
 
 	tmp = in_le32(priv->regbase + EDMA_RQIPR) & ~EDMA_RQIPR_IPMASK;
@@ -477,17 +481,17 @@
 }
 
 /* Get next available slot, ignoring possible overwrite */
-static int get_next_reqip(int port)
+static int get_next_reqip(struct udevice *dev, int port)
 {
-	int slot = get_reqip(port);
+	int slot = get_reqip(dev, port);
 	slot = (slot + 1) % REQUEST_QUEUE_SIZE;
 	return slot;
 }
 
 /* Get response queue in pointer */
-static int get_rspip(int port)
+static int get_rspip(struct udevice *dev, int port)
 {
-	struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
+	struct mv_priv *priv = dev_get_platdata(dev);
 	u32 tmp;
 
 	tmp = in_le32(priv->regbase + EDMA_RSIPR) & EDMA_RSIPR_IPMASK;
@@ -497,9 +501,9 @@
 }
 
 /* Get response queue out pointer */
-static int get_rspop(int port)
+static int get_rspop(struct udevice *dev, int port)
 {
-	struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
+	struct mv_priv *priv = dev_get_platdata(dev);
 	u32 tmp;
 
 	tmp = in_le32(priv->regbase + EDMA_RSOPR) & EDMA_RSOPR_OPMASK;
@@ -508,15 +512,15 @@
 }
 
 /* Get next response queue pointer  */
-static int get_next_rspop(int port)
+static int get_next_rspop(struct udevice *dev, int port)
 {
-	return (get_rspop(port) + 1) % RESPONSE_QUEUE_SIZE;
+	return (get_rspop(dev, port) + 1) % RESPONSE_QUEUE_SIZE;
 }
 
 /* Set response queue pointer */
-static void set_rspop(int port, int reqin)
+static void set_rspop(struct udevice *dev, int port, int reqin)
 {
-	struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
+	struct mv_priv *priv = dev_get_platdata(dev);
 	u32 tmp;
 
 	tmp = in_le32(priv->regbase + EDMA_RSOPR) & ~EDMA_RSOPR_OPMASK;
@@ -525,7 +529,8 @@
 	out_le32(priv->regbase + EDMA_RSOPR, tmp);
 }
 
-static int wait_dma_completion(int port, int index, u32 timeout_msec)
+static int wait_dma_completion(struct udevice *dev, int port, int index,
+			       u32 timeout_msec)
 {
 	u32 tmp, res;
 
@@ -538,13 +543,13 @@
 	return res;
 }
 
-static void process_responses(int port)
+static void process_responses(struct udevice *dev, int port)
 {
 #ifdef DEBUG
-	struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
+	struct mv_priv *priv = dev_get_platdata(dev);
 #endif
 	u32 tmp;
-	u32 outind = get_rspop(port);
+	u32 outind = get_rspop(dev, port);
 
 	/* Ack interrupts */
 	tmp = in_le32(SATAHC_BASE + SATAHC_ICR);
@@ -555,20 +560,21 @@
 	tmp &= ~(BIT(4));
 	out_le32(SATAHC_BASE + SATAHC_ICR, tmp);
 
-	while (get_rspip(port) != outind) {
+	while (get_rspip(dev, port) != outind) {
 #ifdef DEBUG
 		debug("Response index %d flags %08x on port %d\n", outind,
 		      priv->response[outind].flags, port);
 #endif
-		outind = get_next_rspop(port);
-		set_rspop(port, outind);
+		outind = get_next_rspop(dev, port);
+		set_rspop(dev, port, outind);
 	}
 }
 
-static int mv_ata_exec_ata_cmd(int port, struct sata_fis_h2d *cfis,
+static int mv_ata_exec_ata_cmd(struct udevice *dev, int port,
+			       struct sata_fis_h2d *cfis,
 			       u8 *buffer, u32 len, u32 iswrite)
 {
-	struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
+	struct mv_priv *priv = dev_get_platdata(dev);
 	struct crqb *req;
 	int slot;
 	u32 start;
@@ -579,7 +585,7 @@
 	}
 
 	/* Initialize request */
-	slot = get_reqip(port);
+	slot = get_reqip(dev, port);
 	memset(&priv->request[slot], 0, sizeof(struct crqb));
 	req = &priv->request[slot];
 
@@ -633,16 +639,16 @@
 			   start + ALIGN(sizeof(*req), ARCH_DMA_MINALIGN));
 
 	/* Trigger operation */
-	slot = get_next_reqip(port);
-	set_reqip(port, slot);
+	slot = get_next_reqip(dev, port);
+	set_reqip(dev, port, slot);
 
 	/* Wait for completion */
-	if (wait_dma_completion(port, slot, 10000)) {
+	if (wait_dma_completion(dev, port, slot, 10000)) {
 		printf("ATA operation timed out\n");
 		return -1;
 	}
 
-	process_responses(port);
+	process_responses(dev, port);
 
 	/* Invalidate data on read */
 	if (buffer && len) {
@@ -654,7 +660,8 @@
 	return len;
 }
 
-static u32 mv_sata_rw_cmd_ext(int port, lbaint_t start, u32 blkcnt,
+static u32 mv_sata_rw_cmd_ext(struct udevice *dev, int port, lbaint_t start,
+			      u32 blkcnt,
 			      u8 *buffer, int is_write)
 {
 	struct sata_fis_h2d cfis;
@@ -678,14 +685,14 @@
 	cfis.sector_count_exp = (blkcnt >> 8) & 0xff;
 	cfis.sector_count = blkcnt & 0xff;
 
-	res = mv_ata_exec_ata_cmd(port, &cfis, buffer, ATA_SECT_SIZE * blkcnt,
-				  is_write);
+	res = mv_ata_exec_ata_cmd(dev, port, &cfis, buffer,
+				  ATA_SECT_SIZE * blkcnt, is_write);
 
 	return res >= 0 ? blkcnt : res;
 }
 
-static u32 mv_sata_rw_cmd(int port, lbaint_t start, u32 blkcnt, u8 *buffer,
-			  int is_write)
+static u32 mv_sata_rw_cmd(struct udevice *dev, int port, lbaint_t start,
+			  u32 blkcnt, u8 *buffer, int is_write)
 {
 	struct sata_fis_h2d cfis;
 	lbaint_t block;
@@ -705,20 +712,21 @@
 	cfis.lba_low = block & 0xff;
 	cfis.sector_count = (u8)(blkcnt & 0xff);
 
-	res = mv_ata_exec_ata_cmd(port, &cfis, buffer, ATA_SECT_SIZE * blkcnt,
-				  is_write);
+	res = mv_ata_exec_ata_cmd(dev, port, &cfis, buffer,
+				  ATA_SECT_SIZE * blkcnt, is_write);
 
 	return res >= 0 ? blkcnt : res;
 }
 
-static u32 ata_low_level_rw(int dev, lbaint_t blknr, lbaint_t blkcnt,
-			    void *buffer, int is_write)
+static u32 ata_low_level_rw(struct udevice *dev, int port, lbaint_t blknr,
+			    lbaint_t blkcnt, void *buffer, int is_write)
 {
+	struct blk_desc *desc = dev_get_uclass_platdata(dev);
 	lbaint_t start, blks;
 	u8 *addr;
 	int max_blks;
 
-	debug("%s: %ld %ld\n", __func__, blknr, blkcnt);
+	debug("%s: " LBAFU " " LBAFU "\n", __func__, blknr, blkcnt);
 
 	start = blknr;
 	blks = blkcnt;
@@ -727,22 +735,22 @@
 	max_blks = MV_ATA_MAX_SECTORS;
 	do {
 		if (blks > max_blks) {
-			if (sata_dev_desc[dev].lba48) {
-				mv_sata_rw_cmd_ext(dev, start, max_blks, addr,
-						   is_write);
+			if (desc->lba48) {
+				mv_sata_rw_cmd_ext(dev, port, start, max_blks,
+						   addr, is_write);
 			} else {
-				mv_sata_rw_cmd(dev, start, max_blks, addr,
-					       is_write);
+				mv_sata_rw_cmd(dev, port, start, max_blks,
+					       addr, is_write);
 			}
 			start += max_blks;
 			blks -= max_blks;
 			addr += ATA_SECT_SIZE * max_blks;
 		} else {
-			if (sata_dev_desc[dev].lba48) {
-				mv_sata_rw_cmd_ext(dev, start, blks, addr,
+			if (desc->lba48) {
+				mv_sata_rw_cmd_ext(dev, port, start, blks, addr,
 						   is_write);
 			} else {
-				mv_sata_rw_cmd(dev, start, blks, addr,
+				mv_sata_rw_cmd(dev, port, start, blks, addr,
 					       is_write);
 			}
 			start += blks;
@@ -754,11 +762,11 @@
 	return blkcnt;
 }
 
-static int mv_ata_exec_ata_cmd_nondma(int port,
+static int mv_ata_exec_ata_cmd_nondma(struct udevice *dev, int port,
 				      struct sata_fis_h2d *cfis, u8 *buffer,
 				      u32 len, u32 iswrite)
 {
-	struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
+	struct mv_priv *priv = dev_get_platdata(dev);
 	int i;
 	u16 *tp;
 
@@ -791,7 +799,7 @@
 	return len;
 }
 
-static int mv_sata_identify(int port, u16 *id)
+static int mv_sata_identify(struct udevice *dev, int port, u16 *id)
 {
 	struct sata_fis_h2d h2d;
 
@@ -803,13 +811,13 @@
 	/* Give device time to get operational */
 	mdelay(10);
 
-	return mv_ata_exec_ata_cmd_nondma(port, &h2d, (u8 *)id,
+	return mv_ata_exec_ata_cmd_nondma(dev, port, &h2d, (u8 *)id,
 					  ATA_ID_WORDS * 2, READ_CMD);
 }
 
-static void mv_sata_xfer_mode(int port, u16 *id)
+static void mv_sata_xfer_mode(struct udevice *dev, int port, u16 *id)
 {
-	struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
+	struct mv_priv *priv = dev_get_platdata(dev);
 
 	priv->pio = id[ATA_ID_PIO_MODES];
 	priv->mwdma = id[ATA_ID_MWDMA_MODES];
@@ -818,9 +826,9 @@
 	      priv->udma);
 }
 
-static void mv_sata_set_features(int port)
+static void mv_sata_set_features(struct udevice *dev, int port)
 {
-	struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
+	struct mv_priv *priv = dev_get_platdata(dev);
 	struct sata_fis_h2d cfis;
 	u8 udma_cap;
 
@@ -842,55 +850,9 @@
 	if (udma_cap == ATA_UDMA3)
 		cfis.sector_count = XFER_UDMA_3;
 
-	mv_ata_exec_ata_cmd_nondma(port, &cfis, NULL, 0, READ_CMD);
+	mv_ata_exec_ata_cmd_nondma(dev, port, &cfis, NULL, 0, READ_CMD);
 }
 
-int mv_sata_spin_down(int dev)
-{
-	struct sata_fis_h2d cfis;
-	struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[dev].priv;
-
-	if (priv->link == 0) {
-		debug("No device on port: %d\n", dev);
-		return 1;
-	}
-
-	memset(&cfis, 0, sizeof(struct sata_fis_h2d));
-
-	cfis.fis_type = SATA_FIS_TYPE_REGISTER_H2D;
-	cfis.command = ATA_CMD_STANDBY;
-
-	return mv_ata_exec_ata_cmd_nondma(dev, &cfis, NULL, 0, READ_CMD);
-}
-
-int mv_sata_spin_up(int dev)
-{
-	struct sata_fis_h2d cfis;
-	struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[dev].priv;
-
-	if (priv->link == 0) {
-		debug("No device on port: %d\n", dev);
-		return 1;
-	}
-
-	memset(&cfis, 0, sizeof(struct sata_fis_h2d));
-
-	cfis.fis_type = SATA_FIS_TYPE_REGISTER_H2D;
-	cfis.command = ATA_CMD_IDLE;
-
-	return mv_ata_exec_ata_cmd_nondma(dev, &cfis, NULL, 0, READ_CMD);
-}
-
-ulong sata_read(int dev, ulong blknr, lbaint_t blkcnt, void *buffer)
-{
-	return ata_low_level_rw(dev, blknr, blkcnt, buffer, READ_CMD);
-}
-
-ulong sata_write(int dev, ulong blknr, lbaint_t blkcnt, const void *buffer)
-{
-	return ata_low_level_rw(dev, blknr, blkcnt, (void *)buffer, WRITE_CMD);
-}
-
 /*
  * Initialize SATA memory windows
  */
@@ -916,25 +878,17 @@
 	}
 }
 
-int init_sata(int dev)
+static int sata_mv_init_sata(struct udevice *dev, int port)
 {
-	struct mv_priv *priv;
+	struct mv_priv *priv = dev_get_platdata(dev);
 
-	debug("Initialize sata dev: %d\n", dev);
+	debug("Initialize sata dev: %d\n", port);
 
-	if (dev < 0 || dev >= CONFIG_SYS_SATA_MAX_DEVICE) {
-		printf("Invalid sata device %d\n", dev);
+	if (port < 0 || port >= CONFIG_SYS_SATA_MAX_DEVICE) {
+		printf("Invalid sata device %d\n", port);
 		return -1;
 	}
 
-	priv = (struct mv_priv *)malloc(sizeof(struct mv_priv));
-	if (!priv) {
-		printf("Failed to allocate memory for private sata data\n");
-		return -ENOMEM;
-	}
-
-	memset((void *)priv, 0, sizeof(struct mv_priv));
-
 	/* Allocate and align request buffer */
 	priv->crqb_alloc = malloc(sizeof(struct crqb) * REQUEST_QUEUE_SIZE +
 				  CRQB_ALIGN);
@@ -959,11 +913,9 @@
 	priv->response = (struct crpb *)(((u32) priv->crpb_alloc + CRPB_ALIGN) &
 					 ~(CRPB_ALIGN - 1));
 
-	sata_dev_desc[dev].priv = (void *)priv;
+	sprintf(priv->name, "SATA%d", port);
 
-	sprintf(priv->name, "SATA%d", dev);
-
-	priv->regbase = dev == 0 ? SATA0_BASE : SATA1_BASE;
+	priv->regbase = port == 0 ? SATA0_BASE : SATA1_BASE;
 
 	if (!hw_init) {
 		debug("Initialize sata hw\n");
@@ -972,9 +924,9 @@
 		mvsata_ide_conf_mbus_windows();
 	}
 
-	mv_reset_port(dev);
+	mv_reset_port(dev, port);
 
-	if (probe_port(dev)) {
+	if (probe_port(dev, port)) {
 		priv->link = 0;
 		return -ENODEV;
 	}
@@ -983,19 +935,15 @@
 	return 0;
 }
 
-int reset_sata(int dev)
+static int sata_mv_scan_sata(struct udevice *dev, int port)
 {
-	return 0;
-}
-
-int scan_sata(int port)
-{
+	struct blk_desc *desc = dev_get_uclass_platdata(dev);
+	struct mv_priv *priv = dev_get_platdata(dev);
 	unsigned char serial[ATA_ID_SERNO_LEN + 1];
 	unsigned char firmware[ATA_ID_FW_REV_LEN + 1];
 	unsigned char product[ATA_ID_PROD_LEN + 1];
 	u64 n_sectors;
 	u16 *id;
-	struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
 
 	if (!priv->link)
 		return -ENODEV;
@@ -1006,7 +954,7 @@
 		return -ENOMEM;
 	}
 
-	mv_sata_identify(port, id);
+	mv_sata_identify(dev, port, id);
 	ata_swap_buf_le16(id, ATA_ID_WORDS);
 #ifdef DEBUG
 	ata_dump_id(id);
@@ -1014,23 +962,23 @@
 
 	/* Serial number */
 	ata_id_c_string(id, serial, ATA_ID_SERNO, sizeof(serial));
-	memcpy(sata_dev_desc[port].product, serial, sizeof(serial));
+	memcpy(desc->product, serial, sizeof(serial));
 
 	/* Firmware version */
 	ata_id_c_string(id, firmware, ATA_ID_FW_REV, sizeof(firmware));
-	memcpy(sata_dev_desc[port].revision, firmware, sizeof(firmware));
+	memcpy(desc->revision, firmware, sizeof(firmware));
 
 	/* Product model */
 	ata_id_c_string(id, product, ATA_ID_PROD, sizeof(product));
-	memcpy(sata_dev_desc[port].vendor, product, sizeof(product));
+	memcpy(desc->vendor, product, sizeof(product));
 
 	/* Total sectors */
 	n_sectors = ata_id_n_sectors(id);
-	sata_dev_desc[port].lba = n_sectors;
+	desc->lba = n_sectors;
 
 	/* Check if support LBA48 */
 	if (ata_id_has_lba48(id)) {
-		sata_dev_desc[port].lba48 = 1;
+		desc->lba48 = 1;
 		debug("Device support LBA48\n");
 	}
 
@@ -1038,13 +986,111 @@
 	priv->queue_depth = ata_id_queue_depth(id);
 
 	/* Get the xfer mode from device */
-	mv_sata_xfer_mode(port, id);
+	mv_sata_xfer_mode(dev, port, id);
 
 	/* Set the xfer mode to highest speed */
-	mv_sata_set_features(port);
+	mv_sata_set_features(dev, port);
 
 	/* Start up */
-	mv_start_edma_engine(port);
+	mv_start_edma_engine(dev, port);
+
+	return 0;
+}
+
+static ulong sata_mv_read(struct udevice *blk, lbaint_t blknr,
+			  lbaint_t blkcnt, void *buffer)
+{
+	struct mv_priv *priv = dev_get_platdata(blk);
+
+	return ata_low_level_rw(blk, priv->dev_nr, blknr, blkcnt,
+				buffer, READ_CMD);
+}
+
+static ulong sata_mv_write(struct udevice *blk, lbaint_t blknr,
+			   lbaint_t blkcnt, const void *buffer)
+{
+	struct mv_priv *priv = dev_get_platdata(blk);
+
+	return ata_low_level_rw(blk, priv->dev_nr, blknr, blkcnt,
+				(void *)buffer, WRITE_CMD);
+}
+
+static const struct blk_ops sata_mv_blk_ops = {
+	.read	= sata_mv_read,
+	.write	= sata_mv_write,
+};
+
+U_BOOT_DRIVER(sata_mv_driver) = {
+	.name = "sata_mv_blk",
+	.id = UCLASS_BLK,
+	.ops = &sata_mv_blk_ops,
+	.platdata_auto_alloc_size = sizeof(struct mv_priv),
+};
+
+static int sata_mv_probe(struct udevice *dev)
+{
+	const void *blob = gd->fdt_blob;
+	int node = dev_of_offset(dev);
+	struct mv_priv *priv;
+	struct udevice *blk;
+	int nr_ports;
+	int ret;
+	int i;
+
+	/* Get number of ports of this SATA controller */
+	nr_ports = min(fdtdec_get_int(blob, node, "nr-ports", -1),
+		       CONFIG_SYS_SATA_MAX_DEVICE);
+
+	for (i = 0; i < nr_ports; i++) {
+		ret = blk_create_devicef(dev, "sata_mv_blk", "blk",
+					 IF_TYPE_SATA, -1, 512, 0, &blk);
+		if (ret) {
+			debug("Can't create device\n");
+			return ret;
+		}
+
+		priv = dev_get_platdata(blk);
+		priv->dev_nr = i;
+
+		/* Init SATA port */
+		ret = sata_mv_init_sata(blk, i);
+		if (ret) {
+			debug("%s: Failed to init bus\n", __func__);
+			return ret;
+		}
+
+		/* Scan SATA port */
+		ret = sata_mv_scan_sata(blk, i);
+		if (ret) {
+			debug("%s: Failed to scan bus\n", __func__);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int sata_mv_scan(struct udevice *dev)
+{
+	/* Nothing to do here */
 
 	return 0;
 }
+
+static const struct udevice_id sata_mv_ids[] = {
+	{ .compatible = "marvell,armada-370-sata" },
+	{ .compatible = "marvell,orion-sata" },
+	{ }
+};
+
+struct ahci_ops sata_mv_ahci_ops = {
+	.scan = sata_mv_scan,
+};
+
+U_BOOT_DRIVER(sata_mv_ahci) = {
+	.name = "sata_mv_ahci",
+	.id = UCLASS_AHCI,
+	.of_match = sata_mv_ids,
+	.ops = &sata_mv_ahci_ops,
+	.probe = sata_mv_probe,
+};
diff --git a/drivers/clk/altera/clk-arria10.c b/drivers/clk/altera/clk-arria10.c
index 612a171..179869d 100644
--- a/drivers/clk/altera/clk-arria10.c
+++ b/drivers/clk/altera/clk-arria10.c
@@ -254,7 +254,8 @@
 		    fdt_node_check_compatible(fdt, offset, "fixed-clock"))
 			continue;
 
-		if (pre_reloc_only && !dm_fdt_pre_reloc(fdt, offset))
+		if (pre_reloc_only &&
+		    !dm_ofnode_pre_reloc(offset_to_ofnode(offset)))
 			continue;
 
 		ret = device_bind_driver_to_node(dev, "clk-a10", name,
diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c
index 7cfbabc..6b55ec5 100644
--- a/drivers/clk/at91/pmc.c
+++ b/drivers/clk/at91/pmc.c
@@ -61,7 +61,7 @@
 	     offset > 0;
 	     offset = fdt_next_subnode(fdt, offset)) {
 		if (pre_reloc_only &&
-		    !dm_fdt_pre_reloc(fdt, offset))
+		    !dm_ofnode_pre_reloc(offset_to_ofnode(offset)))
 			continue;
 		/*
 		 * If this node has "compatible" property, this is not
diff --git a/drivers/clk/clk_stm32mp1.c b/drivers/clk/clk_stm32mp1.c
index aebc6f0..24859fd 100644
--- a/drivers/clk/clk_stm32mp1.c
+++ b/drivers/clk/clk_stm32mp1.c
@@ -15,10 +15,12 @@
 #include <dt-bindings/clock/stm32mp1-clks.h>
 #include <dt-bindings/clock/stm32mp1-clksrc.h>
 
+#ifndef CONFIG_STM32MP1_TRUSTED
 #if !defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD)
 /* activate clock tree initialization in the driver */
 #define STM32MP1_CLOCK_TREE_INIT
 #endif
+#endif
 
 #define MAX_HSI_HZ		64000000
 
diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c
index 0e584c1..785f5c3 100644
--- a/drivers/core/ofnode.c
+++ b/drivers/core/ofnode.c
@@ -254,14 +254,13 @@
 fdt_addr_t ofnode_get_addr_index(ofnode node, int index)
 {
 	int na, ns;
-	fdt_size_t size;
 
 	if (ofnode_is_np(node)) {
 		const __be32 *prop_val;
 		uint flags;
 
 		prop_val = of_get_address(ofnode_to_np(node), index,
-					  (u64 *)&size, &flags);
+					  NULL, &flags);
 		if (!prop_val)
 			return FDT_ADDR_T_NONE;
 
@@ -278,7 +277,7 @@
 		ns = ofnode_read_simple_size_cells(ofnode_get_parent(node));
 		return fdtdec_get_addr_size_fixed(gd->fdt_blob,
 						  ofnode_to_offset(node), "reg",
-						  index, na, ns, &size, true);
+						  index, na, ns, NULL, true);
 	}
 
 	return FDT_ADDR_T_NONE;
@@ -700,18 +699,18 @@
 
 bool ofnode_pre_reloc(ofnode node)
 {
+#if defined(CONFIG_SPL_BUILD) || defined(CONFIG_TPL_BUILD)
+	/* for SPL and TPL the remaining nodes after the fdtgrep 1st pass
+	 * had property dm-pre-reloc or u-boot,dm-spl/tpl.
+	 * They are removed in final dtb (fdtgrep 2nd pass)
+	 */
+	return true;
+#else
 	if (ofnode_read_bool(node, "u-boot,dm-pre-reloc"))
 		return true;
 	if (ofnode_read_bool(node, "u-boot,dm-pre-proper"))
 		return true;
 
-#ifdef CONFIG_TPL_BUILD
-	if (ofnode_read_bool(node, "u-boot,dm-tpl"))
-		return true;
-#elif defined(CONFIG_SPL_BUILD)
-	if (ofnode_read_bool(node, "u-boot,dm-spl"))
-		return true;
-#else
 	/*
 	 * In regular builds individual spl and tpl handling both
 	 * count as handled pre-relocation for later second init.
@@ -719,9 +718,9 @@
 	if (ofnode_read_bool(node, "u-boot,dm-spl") ||
 	    ofnode_read_bool(node, "u-boot,dm-tpl"))
 		return true;
-#endif
 
 	return false;
+#endif
 }
 
 int ofnode_read_resource(ofnode node, uint index, struct resource *res)
diff --git a/drivers/core/syscon-uclass.c b/drivers/core/syscon-uclass.c
index afac6d6..5bb38e3 100644
--- a/drivers/core/syscon-uclass.c
+++ b/drivers/core/syscon-uclass.c
@@ -57,18 +57,64 @@
 #endif
 }
 
+static int syscon_probe_by_ofnode(ofnode node, struct udevice **devp)
+{
+	struct udevice *dev, *parent;
+	int ret;
+
+	/* found node with "syscon" compatible, not bounded to SYSCON UCLASS */
+	if (!ofnode_device_is_compatible(node, "syscon")) {
+		dev_dbg(dev, "invalid compatible for syscon device\n");
+		return -EINVAL;
+	}
+
+	/* bound to driver with same ofnode or to root if not found */
+	if (device_find_global_by_ofnode(node, &parent))
+		parent = dm_root();
+
+	/* force bound to syscon class */
+	ret = device_bind_driver_to_node(parent, "syscon",
+					 ofnode_get_name(node),
+					 node, &dev);
+	if (ret) {
+		dev_dbg(dev, "unable to bound syscon device\n");
+		return ret;
+	}
+	ret = device_probe(dev);
+	if (ret) {
+		dev_dbg(dev, "unable to probe syscon device\n");
+		return ret;
+	}
+
+	*devp = dev;
+	return 0;
+}
+
 struct regmap *syscon_regmap_lookup_by_phandle(struct udevice *dev,
 					       const char *name)
 {
 	struct udevice *syscon;
 	struct regmap *r;
+	u32 phandle;
+	ofnode node;
 	int err;
 
 	err = uclass_get_device_by_phandle(UCLASS_SYSCON, dev,
 					   name, &syscon);
 	if (err) {
-		dev_dbg(dev, "unable to find syscon device\n");
-		return ERR_PTR(err);
+		/* found node with "syscon" compatible, not bounded to SYSCON */
+		err = ofnode_read_u32(dev_ofnode(dev), name, &phandle);
+		if (err)
+			return ERR_PTR(err);
+
+		node = ofnode_get_by_phandle(phandle);
+		if (!ofnode_valid(node)) {
+			dev_dbg(dev, "unable to find syscon device\n");
+			return ERR_PTR(-EINVAL);
+		}
+		err = syscon_probe_by_ofnode(node, &syscon);
+		if (err)
+			return ERR_PTR(-ENODEV);
 	}
 
 	r = syscon_get_regmap(syscon);
@@ -152,29 +198,18 @@
  */
 struct regmap *syscon_node_to_regmap(ofnode node)
 {
-	struct udevice *dev, *parent;
-	int ret;
-
-	if (!uclass_get_device_by_ofnode(UCLASS_SYSCON, node, &dev))
-		return syscon_get_regmap(dev);
-
-	if (!ofnode_device_is_compatible(node, "syscon"))
-		return ERR_PTR(-EINVAL);
-
-	/* bound to driver with same ofnode or to root if not found */
-	if (device_find_global_by_ofnode(node, &parent))
-		parent = dm_root();
+	struct udevice *dev;
+	struct regmap *r;
 
-	/* force bound to syscon class */
-	ret = device_bind_driver_to_node(parent, "syscon",
-					 ofnode_get_name(node),
-					 node, &dev);
-	if (ret)
-		return ERR_PTR(ret);
+	if (uclass_get_device_by_ofnode(UCLASS_SYSCON, node, &dev))
+		if (syscon_probe_by_ofnode(node, &dev))
+			return ERR_PTR(-ENODEV);
 
-	ret = device_probe(dev);
-	if (ret)
-		return ERR_PTR(ret);
+	r = syscon_get_regmap(dev);
+	if (!r) {
+		dev_dbg(dev, "unable to find regmap\n");
+		return ERR_PTR(-ENODEV);
+	}
 
-	return syscon_get_regmap(dev);
+	return r;
 }
diff --git a/drivers/core/util.c b/drivers/core/util.c
index 27a6848..96e47dc 100644
--- a/drivers/core/util.c
+++ b/drivers/core/util.c
@@ -31,42 +31,18 @@
 	return count;
 }
 
-bool dm_fdt_pre_reloc(const void *blob, int offset)
-{
-	if (fdt_getprop(blob, offset, "u-boot,dm-pre-reloc", NULL))
-		return true;
-
-#ifdef CONFIG_TPL_BUILD
-	if (fdt_getprop(blob, offset, "u-boot,dm-tpl", NULL))
-		return true;
-#elif defined(CONFIG_SPL_BUILD)
-	if (fdt_getprop(blob, offset, "u-boot,dm-spl", NULL))
-		return true;
-#else
-	/*
-	 * In regular builds individual spl and tpl handling both
-	 * count as handled pre-relocation for later second init.
-	 */
-	if (fdt_getprop(blob, offset, "u-boot,dm-spl", NULL) ||
-	    fdt_getprop(blob, offset, "u-boot,dm-tpl", NULL))
-		return true;
-#endif
-
-	return false;
-}
-
 bool dm_ofnode_pre_reloc(ofnode node)
 {
+#if defined(CONFIG_SPL_BUILD) || defined(CONFIG_TPL_BUILD)
+	/* for SPL and TPL the remaining nodes after the fdtgrep 1st pass
+	 * had property dm-pre-reloc or u-boot,dm-spl/tpl.
+	 * They are removed in final dtb (fdtgrep 2nd pass)
+	 */
+	return true;
+#else
 	if (ofnode_read_bool(node, "u-boot,dm-pre-reloc"))
 		return true;
 
-#ifdef CONFIG_TPL_BUILD
-	if (ofnode_read_bool(node, "u-boot,dm-tpl"))
-		return true;
-#elif defined(CONFIG_SPL_BUILD)
-	if (ofnode_read_bool(node, "u-boot,dm-spl"))
-		return true;
-#else
 	/*
 	 * In regular builds individual spl and tpl handling both
 	 * count as handled pre-relocation for later second init.
@@ -74,7 +50,7 @@
 	if (ofnode_read_bool(node, "u-boot,dm-spl") ||
 	    ofnode_read_bool(node, "u-boot,dm-tpl"))
 		return true;
-#endif
 
 	return false;
+#endif
 }
diff --git a/drivers/ddr/marvell/axp/xor_regs.h b/drivers/ddr/marvell/axp/xor_regs.h
index db5c419..d779e56 100644
--- a/drivers/ddr/marvell/axp/xor_regs.h
+++ b/drivers/ddr/marvell/axp/xor_regs.h
@@ -13,7 +13,11 @@
 #define XOR_UNIT(chan)			((chan) >> 1)
 #define XOR_CHAN(chan)			((chan) & 1)
 
+#ifdef CONFIG_ARMADA_MSYS
+#define MV_XOR_REGS_OFFSET(unit)	(0xF0800)
+#else
 #define MV_XOR_REGS_OFFSET(unit)	(0x60900)
+#endif
 #define MV_XOR_REGS_BASE(unit)		(MV_XOR_REGS_OFFSET(unit))
 
 /* XOR Engine Control Register Map */
diff --git a/drivers/dma/bcm6348-iudma.c b/drivers/dma/bcm6348-iudma.c
index 1d3c192..e7bd1b2 100644
--- a/drivers/dma/bcm6348-iudma.c
+++ b/drivers/dma/bcm6348-iudma.c
@@ -324,6 +324,9 @@
 	struct bcm6348_dma_desc *dma_desc = dma_desc = ch_priv->dma_ring;
 	int ret;
 
+	if (!ch_priv->running)
+		return -EINVAL;
+
 	/* get dma ring descriptor address */
 	dma_desc += ch_priv->desc_id;
 
@@ -369,6 +372,9 @@
 	struct bcm6348_dma_desc *dma_desc;
 	uint16_t status;
 
+	if (!ch_priv->running)
+                return -EINVAL;
+
 	/* flush cache */
 	bcm6348_iudma_fdc(src, len);
 
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index b103180..b3e4ecc 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -23,7 +23,7 @@
 
 config BCM6345_GPIO
 	bool "BCM6345 GPIO driver"
-	depends on DM_GPIO && ARCH_BMIPS
+	depends on DM_GPIO && (ARCH_BMIPS || ARCH_BCM6858 || ARCH_BCM63158)
 	help
 	  This driver supports the GPIO banks on BCM6345 SoCs.
 
diff --git a/drivers/gpio/bcm6345_gpio.c b/drivers/gpio/bcm6345_gpio.c
index d1f6cfa..71a978c 100644
--- a/drivers/gpio/bcm6345_gpio.c
+++ b/drivers/gpio/bcm6345_gpio.c
@@ -22,7 +22,7 @@
 {
 	struct bcm6345_gpio_priv *priv = dev_get_priv(dev);
 
-	return !!(readl_be(priv->reg_data) & BIT(offset));
+	return !!(readl(priv->reg_data) & BIT(offset));
 }
 
 static int bcm6345_gpio_set_value(struct udevice *dev, unsigned offset,
@@ -31,9 +31,9 @@
 	struct bcm6345_gpio_priv *priv = dev_get_priv(dev);
 
 	if (value)
-		setbits_be32(priv->reg_data, BIT(offset));
+		setbits_32(priv->reg_data, BIT(offset));
 	else
-		clrbits_be32(priv->reg_data, BIT(offset));
+		clrbits_32(priv->reg_data, BIT(offset));
 
 	return 0;
 }
@@ -42,9 +42,9 @@
 				      bool input)
 {
 	if (input)
-		clrbits_be32(dirout, BIT(offset));
+		clrbits_32(dirout, BIT(offset));
 	else
-		setbits_be32(dirout, BIT(offset));
+		setbits_32(dirout, BIT(offset));
 
 	return 0;
 }
@@ -70,7 +70,7 @@
 {
 	struct bcm6345_gpio_priv *priv = dev_get_priv(dev);
 
-	if (readl_be(priv->reg_dirout) & BIT(offset))
+	if (readl(priv->reg_dirout) & BIT(offset))
 		return GPIOF_OUTPUT;
 	else
 		return GPIOF_INPUT;
diff --git a/drivers/i2c/i2c-uclass.c b/drivers/i2c/i2c-uclass.c
index 49e23a0..e47abf1 100644
--- a/drivers/i2c/i2c-uclass.c
+++ b/drivers/i2c/i2c-uclass.c
@@ -593,6 +593,29 @@
 }
 #endif
 
+static int i2c_pre_probe(struct udevice *dev)
+{
+#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
+	struct dm_i2c_bus *i2c = dev_get_uclass_priv(dev);
+	unsigned int max = 0;
+	ofnode node;
+	int ret;
+
+	i2c->max_transaction_bytes = 0;
+	dev_for_each_subnode(node, dev) {
+		ret = ofnode_read_u32(node,
+				      "u-boot,i2c-transaction-bytes",
+				      &max);
+		if (!ret && max > i2c->max_transaction_bytes)
+			i2c->max_transaction_bytes = max;
+	}
+
+	debug("%s: I2C bus: %s max transaction bytes: %d\n", __func__,
+	      dev->name, i2c->max_transaction_bytes);
+#endif
+	return 0;
+}
+
 static int i2c_post_probe(struct udevice *dev)
 {
 #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
@@ -674,6 +697,7 @@
 	.post_bind	= i2c_post_bind,
 	.init		= i2c_uclass_init,
 	.priv_auto_alloc_size = sizeof(struct i2c_priv),
+	.pre_probe      = i2c_pre_probe,
 	.post_probe	= i2c_post_probe,
 	.per_device_auto_alloc_size = sizeof(struct dm_i2c_bus),
 	.per_child_platdata_auto_alloc_size = sizeof(struct dm_i2c_chip),
diff --git a/drivers/i2c/muxes/Kconfig b/drivers/i2c/muxes/Kconfig
index b0da67c..68f1526 100644
--- a/drivers/i2c/muxes/Kconfig
+++ b/drivers/i2c/muxes/Kconfig
@@ -29,11 +29,12 @@
 	tristate "TI PCA954x I2C Mux/switches"
 	depends on I2C_MUX
 	help
-	  If you say yes here you get support for the TI PCA954x
-	  I2C mux/switch devices. It is x width I2C multiplexer which enables to
-	  partitioning I2C bus and connect multiple devices with the same address
-	  to the same I2C controller where driver handles proper routing to
-	  target i2c device. PCA9544 and PCA9548 are supported.
+	  If you say yes here you get support for the TI PCA954x I2C mux/switch
+	  devices. It is x width I2C multiplexer which enables to partitioning
+	  I2C bus and connect multiple devices with the same address to the same
+	  I2C controller where driver handles proper routing to target i2c
+	  device. Supported chips are PCA9543, PCA9544, PCA9547, PCA9548 and
+	  PCA9646.
 
 config I2C_MUX_GPIO
         tristate "GPIO-based I2C multiplexer"
diff --git a/drivers/i2c/muxes/pca954x.c b/drivers/i2c/muxes/pca954x.c
index bd4e9ab..a630ce9 100644
--- a/drivers/i2c/muxes/pca954x.c
+++ b/drivers/i2c/muxes/pca954x.c
@@ -15,6 +15,7 @@
 DECLARE_GLOBAL_DATA_PTR;
 
 enum pca_type {
+	PCA9543,
 	PCA9544,
 	PCA9547,
 	PCA9548,
@@ -22,7 +23,7 @@
 };
 
 struct chip_desc {
-	u8 enable;
+	u8 enable; /* Enable mask in ctl register (used for muxes only) */
 	enum muxtype {
 		pca954x_ismux = 0,
 		pca954x_isswi,
@@ -37,6 +38,10 @@
 };
 
 static const struct chip_desc chips[] = {
+	[PCA9543] = {
+		.muxtype = pca954x_isswi,
+		.width = 2,
+	},
 	[PCA9544] = {
 		.enable = 0x4,
 		.muxtype = pca954x_ismux,
@@ -48,12 +53,10 @@
 		.width = 8,
 	},
 	[PCA9548] = {
-		.enable = 0x8,
 		.muxtype = pca954x_isswi,
 		.width = 8,
 	},
 	[PCA9646] = {
-		.enable = 0x0,
 		.muxtype = pca954x_isswi,
 		.width = 4,
 	},
@@ -89,6 +92,7 @@
 };
 
 static const struct udevice_id pca954x_ids[] = {
+	{ .compatible = "nxp,pca9543", .data = PCA9543 },
 	{ .compatible = "nxp,pca9544", .data = PCA9544 },
 	{ .compatible = "nxp,pca9547", .data = PCA9547 },
 	{ .compatible = "nxp,pca9548", .data = PCA9548 },
diff --git a/drivers/i2c/mxc_i2c.c b/drivers/i2c/mxc_i2c.c
index 9999d9f..5420afb 100644
--- a/drivers/i2c/mxc_i2c.c
+++ b/drivers/i2c/mxc_i2c.c
@@ -354,9 +354,10 @@
 int i2c_idle_bus(struct mxc_i2c_bus *i2c_bus)
 {
 	struct udevice *bus = i2c_bus->bus;
+	struct dm_i2c_bus *i2c = dev_get_uclass_priv(bus);
 	struct gpio_desc *scl_gpio = &i2c_bus->scl_gpio;
 	struct gpio_desc *sda_gpio = &i2c_bus->sda_gpio;
-	int sda, scl;
+	int sda, scl, idle_sclks;
 	int i, ret = 0;
 	ulong elapsed, start_time;
 
@@ -380,8 +381,22 @@
 	if ((sda & scl) == 1)
 		goto exit;		/* Bus is idle already */
 
+	/*
+	 * In most cases it is just enough to generate 8 + 1 SCLK
+	 * clocks to recover I2C slave device from 'stuck' state
+	 * (when for example SW reset was performed, in the middle of
+	 * I2C transmission).
+	 *
+	 * However, there are devices which send data in packets of
+	 * N bytes (N > 1). In such case we do need N * 8 + 1 SCLK
+	 * clocks.
+	 */
+	idle_sclks = 8 + 1;
+
+	if (i2c->max_transaction_bytes > 0)
+		idle_sclks = i2c->max_transaction_bytes * 8 + 1;
 	/* Send high and low on the SCL line */
-	for (i = 0; i < 9; i++) {
+	for (i = 0; i < idle_sclks; i++) {
 		dm_gpio_set_dir_flags(scl_gpio, GPIOD_IS_OUT);
 		dm_gpio_set_value(scl_gpio, 0);
 		udelay(50);
diff --git a/drivers/misc/i2c_eeprom.c b/drivers/misc/i2c_eeprom.c
index 29ad87c..f25d054 100644
--- a/drivers/misc/i2c_eeprom.c
+++ b/drivers/misc/i2c_eeprom.c
@@ -5,6 +5,7 @@
 
 #include <common.h>
 #include <linux/err.h>
+#include <linux/kernel.h>
 #include <dm.h>
 #include <i2c.h>
 #include <i2c_eeprom.h>
@@ -38,7 +39,24 @@
 static int i2c_eeprom_std_write(struct udevice *dev, int offset,
 				const uint8_t *buf, int size)
 {
-	return -ENODEV;
+	struct i2c_eeprom *priv = dev_get_priv(dev);
+	int ret;
+
+	while (size > 0) {
+		int write_size = min_t(int, size, priv->pagesize);
+
+		ret = dm_i2c_write(dev, offset, buf, write_size);
+		if (ret)
+			return ret;
+
+		offset += write_size;
+		buf += write_size;
+		size -= write_size;
+
+		udelay(10000);
+	}
+
+	return 0;
 }
 
 static const struct i2c_eeprom_ops i2c_eeprom_std_ops = {
@@ -50,6 +68,12 @@
 {
 	struct i2c_eeprom *priv = dev_get_priv(dev);
 	u64 data = dev_get_driver_data(dev);
+	u32 pagesize;
+
+	if (dev_read_u32(dev, "pagesize", &pagesize) == 0) {
+		priv->pagesize = pagesize;
+		return 0;
+	}
 
 	/* 6 bit -> page size of up to 2^63 (should be sufficient) */
 	priv->pagewidth = data & 0x3F;
diff --git a/drivers/misc/stm32mp_fuse.c b/drivers/misc/stm32mp_fuse.c
index 33943a2..8dc246b 100644
--- a/drivers/misc/stm32mp_fuse.c
+++ b/drivers/misc/stm32mp_fuse.c
@@ -9,8 +9,10 @@
 #include <errno.h>
 #include <dm/device.h>
 #include <dm/uclass.h>
+#include <power/stpmic1.h>
 
 #define STM32MP_OTP_BANK	0
+#define STM32MP_NVM_BANK	1
 
 /*
  * The 'fuse' command API
@@ -34,6 +36,13 @@
 		ret = 0;
 		break;
 
+#ifdef CONFIG_PMIC_STPMIC1
+	case STM32MP_NVM_BANK:
+		*val = 0;
+		ret = stpmic1_shadow_read_byte(word, (u8 *)val);
+		break;
+#endif /* CONFIG_PMIC_STPMIC1 */
+
 	default:
 		printf("stm32mp %s: wrong value for bank %i\n", __func__, bank);
 		ret = -EINVAL;
@@ -61,6 +70,12 @@
 			return ret;
 		ret = 0;
 		break;
+
+#ifdef CONFIG_PMIC_STPMIC1
+	case STM32MP_NVM_BANK:
+		ret = stpmic1_nvm_write_byte(word, (u8 *)&val);
+		break;
+#endif /* CONFIG_PMIC_STPMIC1 */
 
 	default:
 		printf("stm32mp %s: wrong value for bank %i\n", __func__, bank);
@@ -89,6 +104,13 @@
 		ret = 0;
 		break;
 
+#ifdef CONFIG_PMIC_STPMIC1
+	case STM32MP_NVM_BANK:
+		*val = 0;
+		ret = stpmic1_nvm_read_byte(word, (u8 *)val);
+		break;
+#endif /* CONFIG_PMIC_STPMIC1 */
+
 	default:
 		printf("stm32mp %s: wrong value for bank %i\n", __func__, bank);
 		ret = -EINVAL;
@@ -117,6 +139,12 @@
 		ret = 0;
 		break;
 
+#ifdef CONFIG_PMIC_STPMIC1
+	case STM32MP_NVM_BANK:
+		ret = stpmic1_shadow_write_byte(word, (u8 *)&val);
+		break;
+#endif /* CONFIG_PMIC_STPMIC1 */
+
 	default:
 		printf("stm32mp %s: wrong value for bank %i\n",
 		       __func__, bank);
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index cb7ca38..89ac822 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -1051,13 +1051,13 @@
 		return -EINVAL;
 
 	if (ops->ooblen) {
-		u64 maxooblen;
+		size_t maxooblen;
 
 		if (ops->ooboffs >= mtd_oobavail(mtd, ops))
 			return -EINVAL;
 
-		maxooblen = ((mtd_div_by_ws(mtd->size, mtd) -
-			      mtd_div_by_ws(offs, mtd)) *
+		maxooblen = ((size_t)(mtd_div_by_ws(mtd->size, mtd) -
+				      mtd_div_by_ws(offs, mtd)) *
 			     mtd_oobavail(mtd, ops)) - ops->ooboffs;
 		if (ops->ooblen > maxooblen)
 			return -EINVAL;
diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index 7f76e5e..dc087ab 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -256,6 +256,17 @@
 	  This flag prevent U-boot reconfigure NAND flash controller and reuse
 	  the NAND timing from 1st stage bootloader.
 
+config NAND_STM32_FMC2
+	bool "Support for NAND controller on STM32MP SoCs"
+	depends on ARCH_STM32MP
+	select SYS_NAND_SELF_INIT
+	imply CMD_NAND
+	help
+	  Enables support for NAND Flash chips on SoCs containing the FMC2
+	  NAND controller. This controller is found on STM32MP SoCs.
+	  The controller supports a maximum 8k page size and supports
+	  a maximum 8-bit correction error per sector of 512 bytes.
+
 comment "Generic NAND options"
 
 config SYS_NAND_BLOCK_SIZE
diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile
index c61e3f3..b10e718 100644
--- a/drivers/mtd/nand/raw/Makefile
+++ b/drivers/mtd/nand/raw/Makefile
@@ -65,6 +65,7 @@
 obj-$(CONFIG_NAND_PLAT) += nand_plat.o
 obj-$(CONFIG_NAND_SUNXI) += sunxi_nand.o
 obj-$(CONFIG_NAND_ZYNQ) += zynq_nand.o
+obj-$(CONFIG_NAND_STM32_FMC2) += stm32_fmc2_nand.o
 
 else  # minimal SPL drivers
 
diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
new file mode 100644
index 0000000..2bb749d
--- /dev/null
+++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
@@ -0,0 +1,1092 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) STMicroelectronics 2019
+ * Author: Christophe Kerello <christophe.kerello@st.com>
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <nand.h>
+#include <reset.h>
+#include <linux/iopoll.h>
+#include <linux/ioport.h>
+
+/* Bad block marker length */
+#define FMC2_BBM_LEN			2
+
+/* ECC step size */
+#define FMC2_ECC_STEP_SIZE		512
+
+/* Command delay */
+#define FMC2_RB_DELAY_US		30
+
+/* Max chip enable */
+#define FMC2_MAX_CE			2
+
+/* Timings */
+#define FMC2_THIZ			1
+#define FMC2_TIO			8000
+#define FMC2_TSYNC			3000
+#define FMC2_PCR_TIMING_MASK		0xf
+#define FMC2_PMEM_PATT_TIMING_MASK	0xff
+
+/* FMC2 Controller Registers */
+#define FMC2_BCR1			0x0
+#define FMC2_PCR			0x80
+#define FMC2_SR				0x84
+#define FMC2_PMEM			0x88
+#define FMC2_PATT			0x8c
+#define FMC2_HECCR			0x94
+#define FMC2_BCHISR			0x254
+#define FMC2_BCHICR			0x258
+#define FMC2_BCHPBR1			0x260
+#define FMC2_BCHPBR2			0x264
+#define FMC2_BCHPBR3			0x268
+#define FMC2_BCHPBR4			0x26c
+#define FMC2_BCHDSR0			0x27c
+#define FMC2_BCHDSR1			0x280
+#define FMC2_BCHDSR2			0x284
+#define FMC2_BCHDSR3			0x288
+#define FMC2_BCHDSR4			0x28c
+
+/* Register: FMC2_BCR1 */
+#define FMC2_BCR1_FMC2EN		BIT(31)
+
+/* Register: FMC2_PCR */
+#define FMC2_PCR_PWAITEN		BIT(1)
+#define FMC2_PCR_PBKEN			BIT(2)
+#define FMC2_PCR_PWID_MASK		GENMASK(5, 4)
+#define FMC2_PCR_PWID(x)		(((x) & 0x3) << 4)
+#define FMC2_PCR_PWID_BUSWIDTH_8	0
+#define FMC2_PCR_PWID_BUSWIDTH_16	1
+#define FMC2_PCR_ECCEN			BIT(6)
+#define FMC2_PCR_ECCALG			BIT(8)
+#define FMC2_PCR_TCLR_MASK		GENMASK(12, 9)
+#define FMC2_PCR_TCLR(x)		(((x) & 0xf) << 9)
+#define FMC2_PCR_TCLR_DEFAULT		0xf
+#define FMC2_PCR_TAR_MASK		GENMASK(16, 13)
+#define FMC2_PCR_TAR(x)			(((x) & 0xf) << 13)
+#define FMC2_PCR_TAR_DEFAULT		0xf
+#define FMC2_PCR_ECCSS_MASK		GENMASK(19, 17)
+#define FMC2_PCR_ECCSS(x)		(((x) & 0x7) << 17)
+#define FMC2_PCR_ECCSS_512		1
+#define FMC2_PCR_ECCSS_2048		3
+#define FMC2_PCR_BCHECC			BIT(24)
+#define FMC2_PCR_WEN			BIT(25)
+
+/* Register: FMC2_SR */
+#define FMC2_SR_NWRF			BIT(6)
+
+/* Register: FMC2_PMEM */
+#define FMC2_PMEM_MEMSET(x)		(((x) & 0xff) << 0)
+#define FMC2_PMEM_MEMWAIT(x)		(((x) & 0xff) << 8)
+#define FMC2_PMEM_MEMHOLD(x)		(((x) & 0xff) << 16)
+#define FMC2_PMEM_MEMHIZ(x)		(((x) & 0xff) << 24)
+#define FMC2_PMEM_DEFAULT		0x0a0a0a0a
+
+/* Register: FMC2_PATT */
+#define FMC2_PATT_ATTSET(x)		(((x) & 0xff) << 0)
+#define FMC2_PATT_ATTWAIT(x)		(((x) & 0xff) << 8)
+#define FMC2_PATT_ATTHOLD(x)		(((x) & 0xff) << 16)
+#define FMC2_PATT_ATTHIZ(x)		(((x) & 0xff) << 24)
+#define FMC2_PATT_DEFAULT		0x0a0a0a0a
+
+/* Register: FMC2_BCHISR */
+#define FMC2_BCHISR_DERF		BIT(1)
+#define FMC2_BCHISR_EPBRF		BIT(4)
+
+/* Register: FMC2_BCHICR */
+#define FMC2_BCHICR_CLEAR_IRQ		GENMASK(4, 0)
+
+/* Register: FMC2_BCHDSR0 */
+#define FMC2_BCHDSR0_DUE		BIT(0)
+#define FMC2_BCHDSR0_DEF		BIT(1)
+#define FMC2_BCHDSR0_DEN_MASK		GENMASK(7, 4)
+#define FMC2_BCHDSR0_DEN_SHIFT		4
+
+/* Register: FMC2_BCHDSR1 */
+#define FMC2_BCHDSR1_EBP1_MASK		GENMASK(12, 0)
+#define FMC2_BCHDSR1_EBP2_MASK		GENMASK(28, 16)
+#define FMC2_BCHDSR1_EBP2_SHIFT		16
+
+/* Register: FMC2_BCHDSR2 */
+#define FMC2_BCHDSR2_EBP3_MASK		GENMASK(12, 0)
+#define FMC2_BCHDSR2_EBP4_MASK		GENMASK(28, 16)
+#define FMC2_BCHDSR2_EBP4_SHIFT		16
+
+/* Register: FMC2_BCHDSR3 */
+#define FMC2_BCHDSR3_EBP5_MASK		GENMASK(12, 0)
+#define FMC2_BCHDSR3_EBP6_MASK		GENMASK(28, 16)
+#define FMC2_BCHDSR3_EBP6_SHIFT		16
+
+/* Register: FMC2_BCHDSR4 */
+#define FMC2_BCHDSR4_EBP7_MASK		GENMASK(12, 0)
+#define FMC2_BCHDSR4_EBP8_MASK		GENMASK(28, 16)
+#define FMC2_BCHDSR4_EBP8_SHIFT		16
+
+#define FMC2_NSEC_PER_SEC		1000000000L
+
+enum stm32_fmc2_ecc {
+	FMC2_ECC_HAM = 1,
+	FMC2_ECC_BCH4 = 4,
+	FMC2_ECC_BCH8 = 8
+};
+
+struct stm32_fmc2_timings {
+	u8 tclr;
+	u8 tar;
+	u8 thiz;
+	u8 twait;
+	u8 thold_mem;
+	u8 tset_mem;
+	u8 thold_att;
+	u8 tset_att;
+};
+
+struct stm32_fmc2_nand {
+	struct nand_chip chip;
+	struct stm32_fmc2_timings timings;
+	int ncs;
+	int cs_used[FMC2_MAX_CE];
+};
+
+static inline struct stm32_fmc2_nand *to_fmc2_nand(struct nand_chip *chip)
+{
+	return container_of(chip, struct stm32_fmc2_nand, chip);
+}
+
+struct stm32_fmc2_nfc {
+	struct nand_hw_control base;
+	struct stm32_fmc2_nand nand;
+	struct nand_ecclayout ecclayout;
+	void __iomem *io_base;
+	void __iomem *data_base[FMC2_MAX_CE];
+	void __iomem *cmd_base[FMC2_MAX_CE];
+	void __iomem *addr_base[FMC2_MAX_CE];
+	struct clk clk;
+
+	u8 cs_assigned;
+	int cs_sel;
+};
+
+static inline struct stm32_fmc2_nfc *to_stm32_nfc(struct nand_hw_control *base)
+{
+	return container_of(base, struct stm32_fmc2_nfc, base);
+}
+
+/* Timings configuration */
+static void stm32_fmc2_timings_init(struct nand_chip *chip)
+{
+	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+	struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
+	struct stm32_fmc2_timings *timings = &nand->timings;
+	u32 pcr = readl(fmc2->io_base + FMC2_PCR);
+	u32 pmem, patt;
+
+	/* Set tclr/tar timings */
+	pcr &= ~FMC2_PCR_TCLR_MASK;
+	pcr |= FMC2_PCR_TCLR(timings->tclr);
+	pcr &= ~FMC2_PCR_TAR_MASK;
+	pcr |= FMC2_PCR_TAR(timings->tar);
+
+	/* Set tset/twait/thold/thiz timings in common bank */
+	pmem = FMC2_PMEM_MEMSET(timings->tset_mem);
+	pmem |= FMC2_PMEM_MEMWAIT(timings->twait);
+	pmem |= FMC2_PMEM_MEMHOLD(timings->thold_mem);
+	pmem |= FMC2_PMEM_MEMHIZ(timings->thiz);
+
+	/* Set tset/twait/thold/thiz timings in attribut bank */
+	patt = FMC2_PATT_ATTSET(timings->tset_att);
+	patt |= FMC2_PATT_ATTWAIT(timings->twait);
+	patt |= FMC2_PATT_ATTHOLD(timings->thold_att);
+	patt |= FMC2_PATT_ATTHIZ(timings->thiz);
+
+	writel(pcr, fmc2->io_base + FMC2_PCR);
+	writel(pmem, fmc2->io_base + FMC2_PMEM);
+	writel(patt, fmc2->io_base + FMC2_PATT);
+}
+
+/* Controller configuration */
+static void stm32_fmc2_setup(struct nand_chip *chip)
+{
+	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+	u32 pcr = readl(fmc2->io_base + FMC2_PCR);
+
+	/* Configure ECC algorithm (default configuration is Hamming) */
+	pcr &= ~FMC2_PCR_ECCALG;
+	pcr &= ~FMC2_PCR_BCHECC;
+	if (chip->ecc.strength == FMC2_ECC_BCH8) {
+		pcr |= FMC2_PCR_ECCALG;
+		pcr |= FMC2_PCR_BCHECC;
+	} else if (chip->ecc.strength == FMC2_ECC_BCH4) {
+		pcr |= FMC2_PCR_ECCALG;
+	}
+
+	/* Set buswidth */
+	pcr &= ~FMC2_PCR_PWID_MASK;
+	if (chip->options & NAND_BUSWIDTH_16)
+		pcr |= FMC2_PCR_PWID(FMC2_PCR_PWID_BUSWIDTH_16);
+
+	/* Set ECC sector size */
+	pcr &= ~FMC2_PCR_ECCSS_MASK;
+	pcr |= FMC2_PCR_ECCSS(FMC2_PCR_ECCSS_512);
+
+	writel(pcr, fmc2->io_base + FMC2_PCR);
+}
+
+/* Select target */
+static void stm32_fmc2_select_chip(struct mtd_info *mtd, int chipnr)
+{
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+	struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
+
+	if (chipnr < 0 || chipnr >= nand->ncs)
+		return;
+
+	if (nand->cs_used[chipnr] == fmc2->cs_sel)
+		return;
+
+	fmc2->cs_sel = nand->cs_used[chipnr];
+	chip->IO_ADDR_R = fmc2->data_base[fmc2->cs_sel];
+	chip->IO_ADDR_W = fmc2->data_base[fmc2->cs_sel];
+
+	/* FMC2 setup routine */
+	stm32_fmc2_setup(chip);
+
+	/* Apply timings */
+	stm32_fmc2_timings_init(chip);
+}
+
+/* Set bus width to 16-bit or 8-bit */
+static void stm32_fmc2_set_buswidth_16(struct stm32_fmc2_nfc *fmc2, bool set)
+{
+	u32 pcr = readl(fmc2->io_base + FMC2_PCR);
+
+	pcr &= ~FMC2_PCR_PWID_MASK;
+	if (set)
+		pcr |= FMC2_PCR_PWID(FMC2_PCR_PWID_BUSWIDTH_16);
+	writel(pcr, fmc2->io_base + FMC2_PCR);
+}
+
+/* Enable/disable ECC */
+static void stm32_fmc2_set_ecc(struct stm32_fmc2_nfc *fmc2, bool enable)
+{
+	u32 pcr = readl(fmc2->io_base + FMC2_PCR);
+
+	pcr &= ~FMC2_PCR_ECCEN;
+	if (enable)
+		pcr |= FMC2_PCR_ECCEN;
+	writel(pcr, fmc2->io_base + FMC2_PCR);
+}
+
+/* Clear irq sources in case of bch is used */
+static inline void stm32_fmc2_clear_bch_irq(struct stm32_fmc2_nfc *fmc2)
+{
+	writel(FMC2_BCHICR_CLEAR_IRQ, fmc2->io_base + FMC2_BCHICR);
+}
+
+/* Send command and address cycles */
+static void stm32_fmc2_cmd_ctrl(struct mtd_info *mtd, int cmd,
+				unsigned int ctrl)
+{
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+
+	if (cmd == NAND_CMD_NONE)
+		return;
+
+	if (ctrl & NAND_CLE) {
+		writeb(cmd, fmc2->cmd_base[fmc2->cs_sel]);
+		return;
+	}
+
+	writeb(cmd, fmc2->addr_base[fmc2->cs_sel]);
+}
+
+/*
+ * Enable ECC logic and reset syndrome/parity bits previously calculated
+ * Syndrome/parity bits is cleared by setting the ECCEN bit to 0
+ */
+static void stm32_fmc2_hwctl(struct mtd_info *mtd, int mode)
+{
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+
+	stm32_fmc2_set_ecc(fmc2, false);
+
+	if (chip->ecc.strength != FMC2_ECC_HAM) {
+		u32 pcr = readl(fmc2->io_base + FMC2_PCR);
+
+		if (mode == NAND_ECC_WRITE)
+			pcr |= FMC2_PCR_WEN;
+		else
+			pcr &= ~FMC2_PCR_WEN;
+		writel(pcr, fmc2->io_base + FMC2_PCR);
+
+		stm32_fmc2_clear_bch_irq(fmc2);
+	}
+
+	stm32_fmc2_set_ecc(fmc2, true);
+}
+
+/*
+ * ECC Hamming calculation
+ * ECC is 3 bytes for 512 bytes of data (supports error correction up to
+ * max of 1-bit)
+ */
+static int stm32_fmc2_ham_calculate(struct mtd_info *mtd, const u8 *data,
+				    u8 *ecc)
+{
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+	u32 heccr, sr;
+	int ret;
+
+	ret = readl_poll_timeout(fmc2->io_base + FMC2_SR, sr,
+				 sr & FMC2_SR_NWRF, 10000);
+	if (ret < 0) {
+		pr_err("Ham timeout\n");
+		return ret;
+	}
+
+	heccr = readl(fmc2->io_base + FMC2_HECCR);
+
+	ecc[0] = heccr;
+	ecc[1] = heccr >> 8;
+	ecc[2] = heccr >> 16;
+
+	/* Disable ecc */
+	stm32_fmc2_set_ecc(fmc2, false);
+
+	return 0;
+}
+
+static int stm32_fmc2_ham_correct(struct mtd_info *mtd, u8 *dat,
+				  u8 *read_ecc, u8 *calc_ecc)
+{
+	u8 bit_position = 0, b0, b1, b2;
+	u32 byte_addr = 0, b;
+	u32 i, shifting = 1;
+
+	/* Indicate which bit and byte is faulty (if any) */
+	b0 = read_ecc[0] ^ calc_ecc[0];
+	b1 = read_ecc[1] ^ calc_ecc[1];
+	b2 = read_ecc[2] ^ calc_ecc[2];
+	b = b0 | (b1 << 8) | (b2 << 16);
+
+	/* No errors */
+	if (likely(!b))
+		return 0;
+
+	/* Calculate bit position */
+	for (i = 0; i < 3; i++) {
+		switch (b % 4) {
+		case 2:
+			bit_position += shifting;
+		case 1:
+			break;
+		default:
+			return -EBADMSG;
+		}
+		shifting <<= 1;
+		b >>= 2;
+	}
+
+	/* Calculate byte position */
+	shifting = 1;
+	for (i = 0; i < 9; i++) {
+		switch (b % 4) {
+		case 2:
+			byte_addr += shifting;
+		case 1:
+			break;
+		default:
+			return -EBADMSG;
+		}
+		shifting <<= 1;
+		b >>= 2;
+	}
+
+	/* Flip the bit */
+	dat[byte_addr] ^= (1 << bit_position);
+
+	return 1;
+}
+
+/*
+ * ECC BCH calculation and correction
+ * ECC is 7/13 bytes for 512 bytes of data (supports error correction up to
+ * max of 4-bit/8-bit)
+ */
+
+static int stm32_fmc2_bch_calculate(struct mtd_info *mtd, const u8 *data,
+				    u8 *ecc)
+{
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+	u32 bchpbr, bchisr;
+	int ret;
+
+	/* Wait until the BCH code is ready */
+	ret = readl_poll_timeout(fmc2->io_base + FMC2_BCHISR, bchisr,
+				 bchisr & FMC2_BCHISR_EPBRF, 10000);
+	if (ret < 0) {
+		pr_err("Bch timeout\n");
+		return ret;
+	}
+
+	/* Read parity bits */
+	bchpbr = readl(fmc2->io_base + FMC2_BCHPBR1);
+	ecc[0] = bchpbr;
+	ecc[1] = bchpbr >> 8;
+	ecc[2] = bchpbr >> 16;
+	ecc[3] = bchpbr >> 24;
+
+	bchpbr = readl(fmc2->io_base + FMC2_BCHPBR2);
+	ecc[4] = bchpbr;
+	ecc[5] = bchpbr >> 8;
+	ecc[6] = bchpbr >> 16;
+
+	if (chip->ecc.strength == FMC2_ECC_BCH8) {
+		ecc[7] = bchpbr >> 24;
+
+		bchpbr = readl(fmc2->io_base + FMC2_BCHPBR3);
+		ecc[8] = bchpbr;
+		ecc[9] = bchpbr >> 8;
+		ecc[10] = bchpbr >> 16;
+		ecc[11] = bchpbr >> 24;
+
+		bchpbr = readl(fmc2->io_base + FMC2_BCHPBR4);
+		ecc[12] = bchpbr;
+	}
+
+	/* Disable ecc */
+	stm32_fmc2_set_ecc(fmc2, false);
+
+	return 0;
+}
+
+/* BCH algorithm correction */
+static int stm32_fmc2_bch_correct(struct mtd_info *mtd, u8 *dat,
+				  u8 *read_ecc, u8 *calc_ecc)
+{
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+	u32 bchdsr0, bchdsr1, bchdsr2, bchdsr3, bchdsr4, bchisr;
+	u16 pos[8];
+	int i, ret, den, eccsize = chip->ecc.size;
+	unsigned int nb_errs = 0;
+
+	/* Wait until the decoding error is ready */
+	ret = readl_poll_timeout(fmc2->io_base + FMC2_BCHISR, bchisr,
+				 bchisr & FMC2_BCHISR_DERF, 10000);
+	if (ret < 0) {
+		pr_err("Bch timeout\n");
+		return ret;
+	}
+
+	bchdsr0 = readl(fmc2->io_base + FMC2_BCHDSR0);
+	bchdsr1 = readl(fmc2->io_base + FMC2_BCHDSR1);
+	bchdsr2 = readl(fmc2->io_base + FMC2_BCHDSR2);
+	bchdsr3 = readl(fmc2->io_base + FMC2_BCHDSR3);
+	bchdsr4 = readl(fmc2->io_base + FMC2_BCHDSR4);
+
+	/* Disable ECC */
+	stm32_fmc2_set_ecc(fmc2, false);
+
+	/* No errors found */
+	if (likely(!(bchdsr0 & FMC2_BCHDSR0_DEF)))
+		return 0;
+
+	/* Too many errors detected */
+	if (unlikely(bchdsr0 & FMC2_BCHDSR0_DUE))
+		return -EBADMSG;
+
+	pos[0] = bchdsr1 & FMC2_BCHDSR1_EBP1_MASK;
+	pos[1] = (bchdsr1 & FMC2_BCHDSR1_EBP2_MASK) >> FMC2_BCHDSR1_EBP2_SHIFT;
+	pos[2] = bchdsr2 & FMC2_BCHDSR2_EBP3_MASK;
+	pos[3] = (bchdsr2 & FMC2_BCHDSR2_EBP4_MASK) >> FMC2_BCHDSR2_EBP4_SHIFT;
+	pos[4] = bchdsr3 & FMC2_BCHDSR3_EBP5_MASK;
+	pos[5] = (bchdsr3 & FMC2_BCHDSR3_EBP6_MASK) >> FMC2_BCHDSR3_EBP6_SHIFT;
+	pos[6] = bchdsr4 & FMC2_BCHDSR4_EBP7_MASK;
+	pos[7] = (bchdsr4 & FMC2_BCHDSR4_EBP8_MASK) >> FMC2_BCHDSR4_EBP8_SHIFT;
+
+	den = (bchdsr0 & FMC2_BCHDSR0_DEN_MASK) >> FMC2_BCHDSR0_DEN_SHIFT;
+	for (i = 0; i < den; i++) {
+		if (pos[i] < eccsize * 8) {
+			__change_bit(pos[i], (unsigned long *)dat);
+			nb_errs++;
+		}
+	}
+
+	return nb_errs;
+}
+
+static int stm32_fmc2_read_page(struct mtd_info *mtd,
+				struct nand_chip *chip, u8 *buf,
+				int oob_required, int page)
+{
+	int i, s, stat, eccsize = chip->ecc.size;
+	int eccbytes = chip->ecc.bytes;
+	int eccsteps = chip->ecc.steps;
+	int eccstrength = chip->ecc.strength;
+	u8 *p = buf;
+	u8 *ecc_calc = chip->buffers->ecccalc;
+	u8 *ecc_code = chip->buffers->ecccode;
+	unsigned int max_bitflips = 0;
+
+	for (i = mtd->writesize + FMC2_BBM_LEN, s = 0; s < eccsteps;
+	     s++, i += eccbytes, p += eccsize) {
+		chip->ecc.hwctl(mtd, NAND_ECC_READ);
+
+		/* Read the nand page sector (512 bytes) */
+		chip->cmdfunc(mtd, NAND_CMD_RNDOUT, s * eccsize, -1);
+		chip->read_buf(mtd, p, eccsize);
+
+		/* Read the corresponding ECC bytes */
+		chip->cmdfunc(mtd, NAND_CMD_RNDOUT, i, -1);
+		chip->read_buf(mtd, ecc_code, eccbytes);
+
+		/* Correct the data */
+		stat = chip->ecc.correct(mtd, p, ecc_code, ecc_calc);
+		if (stat == -EBADMSG)
+			/* Check for empty pages with bitflips */
+			stat = nand_check_erased_ecc_chunk(p, eccsize,
+							   ecc_code, eccbytes,
+							   NULL, 0,
+							   eccstrength);
+
+		if (stat < 0) {
+			mtd->ecc_stats.failed++;
+		} else {
+			mtd->ecc_stats.corrected += stat;
+			max_bitflips = max_t(unsigned int, max_bitflips, stat);
+		}
+	}
+
+	/* Read oob */
+	if (oob_required) {
+		chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1);
+		chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
+	}
+
+	return max_bitflips;
+}
+
+/* Controller initialization */
+static void stm32_fmc2_init(struct stm32_fmc2_nfc *fmc2)
+{
+	u32 pcr = readl(fmc2->io_base + FMC2_PCR);
+	u32 bcr1 = readl(fmc2->io_base + FMC2_BCR1);
+
+	/* Set CS used to undefined */
+	fmc2->cs_sel = -1;
+
+	/* Enable wait feature and nand flash memory bank */
+	pcr |= FMC2_PCR_PWAITEN;
+	pcr |= FMC2_PCR_PBKEN;
+
+	/* Set buswidth to 8 bits mode for identification */
+	pcr &= ~FMC2_PCR_PWID_MASK;
+
+	/* ECC logic is disabled */
+	pcr &= ~FMC2_PCR_ECCEN;
+
+	/* Default mode */
+	pcr &= ~FMC2_PCR_ECCALG;
+	pcr &= ~FMC2_PCR_BCHECC;
+	pcr &= ~FMC2_PCR_WEN;
+
+	/* Set default ECC sector size */
+	pcr &= ~FMC2_PCR_ECCSS_MASK;
+	pcr |= FMC2_PCR_ECCSS(FMC2_PCR_ECCSS_2048);
+
+	/* Set default tclr/tar timings */
+	pcr &= ~FMC2_PCR_TCLR_MASK;
+	pcr |= FMC2_PCR_TCLR(FMC2_PCR_TCLR_DEFAULT);
+	pcr &= ~FMC2_PCR_TAR_MASK;
+	pcr |= FMC2_PCR_TAR(FMC2_PCR_TAR_DEFAULT);
+
+	/* Enable FMC2 controller */
+	bcr1 |= FMC2_BCR1_FMC2EN;
+
+	writel(bcr1, fmc2->io_base + FMC2_BCR1);
+	writel(pcr, fmc2->io_base + FMC2_PCR);
+	writel(FMC2_PMEM_DEFAULT, fmc2->io_base + FMC2_PMEM);
+	writel(FMC2_PATT_DEFAULT, fmc2->io_base + FMC2_PATT);
+}
+
+/* Controller timings */
+static void stm32_fmc2_calc_timings(struct nand_chip *chip,
+				    const struct nand_sdr_timings *sdrt)
+{
+	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+	struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
+	struct stm32_fmc2_timings *tims = &nand->timings;
+	unsigned long hclk = clk_get_rate(&fmc2->clk);
+	unsigned long hclkp = FMC2_NSEC_PER_SEC / (hclk / 1000);
+	int tar, tclr, thiz, twait, tset_mem, tset_att, thold_mem, thold_att;
+
+	tar = hclkp;
+	if (tar < sdrt->tAR_min)
+		tar = sdrt->tAR_min;
+	tims->tar = DIV_ROUND_UP(tar, hclkp) - 1;
+	if (tims->tar > FMC2_PCR_TIMING_MASK)
+		tims->tar = FMC2_PCR_TIMING_MASK;
+
+	tclr = hclkp;
+	if (tclr < sdrt->tCLR_min)
+		tclr = sdrt->tCLR_min;
+	tims->tclr = DIV_ROUND_UP(tclr, hclkp) - 1;
+	if (tims->tclr > FMC2_PCR_TIMING_MASK)
+		tims->tclr = FMC2_PCR_TIMING_MASK;
+
+	tims->thiz = FMC2_THIZ;
+	thiz = (tims->thiz + 1) * hclkp;
+
+	/*
+	 * tWAIT > tRP
+	 * tWAIT > tWP
+	 * tWAIT > tREA + tIO
+	 */
+	twait = hclkp;
+	if (twait < sdrt->tRP_min)
+		twait = sdrt->tRP_min;
+	if (twait < sdrt->tWP_min)
+		twait = sdrt->tWP_min;
+	if (twait < sdrt->tREA_max + FMC2_TIO)
+		twait = sdrt->tREA_max + FMC2_TIO;
+	tims->twait = DIV_ROUND_UP(twait, hclkp);
+	if (tims->twait == 0)
+		tims->twait = 1;
+	else if (tims->twait > FMC2_PMEM_PATT_TIMING_MASK)
+		tims->twait = FMC2_PMEM_PATT_TIMING_MASK;
+
+	/*
+	 * tSETUP_MEM > tCS - tWAIT
+	 * tSETUP_MEM > tALS - tWAIT
+	 * tSETUP_MEM > tDS - (tWAIT - tHIZ)
+	 */
+	tset_mem = hclkp;
+	if (sdrt->tCS_min > twait && (tset_mem < sdrt->tCS_min - twait))
+		tset_mem = sdrt->tCS_min - twait;
+	if (sdrt->tALS_min > twait && (tset_mem < sdrt->tALS_min - twait))
+		tset_mem = sdrt->tALS_min - twait;
+	if (twait > thiz && (sdrt->tDS_min > twait - thiz) &&
+	    (tset_mem < sdrt->tDS_min - (twait - thiz)))
+		tset_mem = sdrt->tDS_min - (twait - thiz);
+	tims->tset_mem = DIV_ROUND_UP(tset_mem, hclkp);
+	if (tims->tset_mem == 0)
+		tims->tset_mem = 1;
+	else if (tims->tset_mem > FMC2_PMEM_PATT_TIMING_MASK)
+		tims->tset_mem = FMC2_PMEM_PATT_TIMING_MASK;
+
+	/*
+	 * tHOLD_MEM > tCH
+	 * tHOLD_MEM > tREH - tSETUP_MEM
+	 * tHOLD_MEM > max(tRC, tWC) - (tSETUP_MEM + tWAIT)
+	 */
+	thold_mem = hclkp;
+	if (thold_mem < sdrt->tCH_min)
+		thold_mem = sdrt->tCH_min;
+	if (sdrt->tREH_min > tset_mem &&
+	    (thold_mem < sdrt->tREH_min - tset_mem))
+		thold_mem = sdrt->tREH_min - tset_mem;
+	if ((sdrt->tRC_min > tset_mem + twait) &&
+	    (thold_mem < sdrt->tRC_min - (tset_mem + twait)))
+		thold_mem = sdrt->tRC_min - (tset_mem + twait);
+	if ((sdrt->tWC_min > tset_mem + twait) &&
+	    (thold_mem < sdrt->tWC_min - (tset_mem + twait)))
+		thold_mem = sdrt->tWC_min - (tset_mem + twait);
+	tims->thold_mem = DIV_ROUND_UP(thold_mem, hclkp);
+	if (tims->thold_mem == 0)
+		tims->thold_mem = 1;
+	else if (tims->thold_mem > FMC2_PMEM_PATT_TIMING_MASK)
+		tims->thold_mem = FMC2_PMEM_PATT_TIMING_MASK;
+
+	/*
+	 * tSETUP_ATT > tCS - tWAIT
+	 * tSETUP_ATT > tCLS - tWAIT
+	 * tSETUP_ATT > tALS - tWAIT
+	 * tSETUP_ATT > tRHW - tHOLD_MEM
+	 * tSETUP_ATT > tDS - (tWAIT - tHIZ)
+	 */
+	tset_att = hclkp;
+	if (sdrt->tCS_min > twait && (tset_att < sdrt->tCS_min - twait))
+		tset_att = sdrt->tCS_min - twait;
+	if (sdrt->tCLS_min > twait && (tset_att < sdrt->tCLS_min - twait))
+		tset_att = sdrt->tCLS_min - twait;
+	if (sdrt->tALS_min > twait && (tset_att < sdrt->tALS_min - twait))
+		tset_att = sdrt->tALS_min - twait;
+	if (sdrt->tRHW_min > thold_mem &&
+	    (tset_att < sdrt->tRHW_min - thold_mem))
+		tset_att = sdrt->tRHW_min - thold_mem;
+	if (twait > thiz && (sdrt->tDS_min > twait - thiz) &&
+	    (tset_att < sdrt->tDS_min - (twait - thiz)))
+		tset_att = sdrt->tDS_min - (twait - thiz);
+	tims->tset_att = DIV_ROUND_UP(tset_att, hclkp);
+	if (tims->tset_att == 0)
+		tims->tset_att = 1;
+	else if (tims->tset_att > FMC2_PMEM_PATT_TIMING_MASK)
+		tims->tset_att = FMC2_PMEM_PATT_TIMING_MASK;
+
+	/*
+	 * tHOLD_ATT > tALH
+	 * tHOLD_ATT > tCH
+	 * tHOLD_ATT > tCLH
+	 * tHOLD_ATT > tCOH
+	 * tHOLD_ATT > tDH
+	 * tHOLD_ATT > tWB + tIO + tSYNC - tSETUP_MEM
+	 * tHOLD_ATT > tADL - tSETUP_MEM
+	 * tHOLD_ATT > tWH - tSETUP_MEM
+	 * tHOLD_ATT > tWHR - tSETUP_MEM
+	 * tHOLD_ATT > tRC - (tSETUP_ATT + tWAIT)
+	 * tHOLD_ATT > tWC - (tSETUP_ATT + tWAIT)
+	 */
+	thold_att = hclkp;
+	if (thold_att < sdrt->tALH_min)
+		thold_att = sdrt->tALH_min;
+	if (thold_att < sdrt->tCH_min)
+		thold_att = sdrt->tCH_min;
+	if (thold_att < sdrt->tCLH_min)
+		thold_att = sdrt->tCLH_min;
+	if (thold_att < sdrt->tCOH_min)
+		thold_att = sdrt->tCOH_min;
+	if (thold_att < sdrt->tDH_min)
+		thold_att = sdrt->tDH_min;
+	if ((sdrt->tWB_max + FMC2_TIO + FMC2_TSYNC > tset_mem) &&
+	    (thold_att < sdrt->tWB_max + FMC2_TIO + FMC2_TSYNC - tset_mem))
+		thold_att = sdrt->tWB_max + FMC2_TIO + FMC2_TSYNC - tset_mem;
+	if (sdrt->tADL_min > tset_mem &&
+	    (thold_att < sdrt->tADL_min - tset_mem))
+		thold_att = sdrt->tADL_min - tset_mem;
+	if (sdrt->tWH_min > tset_mem &&
+	    (thold_att < sdrt->tWH_min - tset_mem))
+		thold_att = sdrt->tWH_min - tset_mem;
+	if (sdrt->tWHR_min > tset_mem &&
+	    (thold_att < sdrt->tWHR_min - tset_mem))
+		thold_att = sdrt->tWHR_min - tset_mem;
+	if ((sdrt->tRC_min > tset_att + twait) &&
+	    (thold_att < sdrt->tRC_min - (tset_att + twait)))
+		thold_att = sdrt->tRC_min - (tset_att + twait);
+	if ((sdrt->tWC_min > tset_att + twait) &&
+	    (thold_att < sdrt->tWC_min - (tset_att + twait)))
+		thold_att = sdrt->tWC_min - (tset_att + twait);
+	tims->thold_att = DIV_ROUND_UP(thold_att, hclkp);
+	if (tims->thold_att == 0)
+		tims->thold_att = 1;
+	else if (tims->thold_att > FMC2_PMEM_PATT_TIMING_MASK)
+		tims->thold_att = FMC2_PMEM_PATT_TIMING_MASK;
+}
+
+static int stm32_fmc2_setup_interface(struct mtd_info *mtd, int chipnr,
+				      const struct nand_data_interface *conf)
+{
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	const struct nand_sdr_timings *sdrt;
+
+	sdrt = nand_get_sdr_timings(conf);
+	if (IS_ERR(sdrt))
+		return PTR_ERR(sdrt);
+
+	if (chipnr == NAND_DATA_IFACE_CHECK_ONLY)
+		return 0;
+
+	stm32_fmc2_calc_timings(chip, sdrt);
+
+	/* Apply timings */
+	stm32_fmc2_timings_init(chip);
+
+	return 0;
+}
+
+/* NAND callbacks setup */
+static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip)
+{
+	chip->ecc.hwctl = stm32_fmc2_hwctl;
+
+	/*
+	 * Specific callbacks to read/write a page depending on
+	 * the algo used (Hamming, BCH).
+	 */
+	if (chip->ecc.strength == FMC2_ECC_HAM) {
+		/* Hamming is used */
+		chip->ecc.calculate = stm32_fmc2_ham_calculate;
+		chip->ecc.correct = stm32_fmc2_ham_correct;
+		chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 4 : 3;
+		chip->ecc.options |= NAND_ECC_GENERIC_ERASED_CHECK;
+		return;
+	}
+
+	/* BCH is used */
+	chip->ecc.read_page = stm32_fmc2_read_page;
+	chip->ecc.calculate = stm32_fmc2_bch_calculate;
+	chip->ecc.correct = stm32_fmc2_bch_correct;
+
+	if (chip->ecc.strength == FMC2_ECC_BCH8)
+		chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 14 : 13;
+	else
+		chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 8 : 7;
+}
+
+/* FMC2 caps */
+static int stm32_fmc2_calc_ecc_bytes(int step_size, int strength)
+{
+	/* Hamming */
+	if (strength == FMC2_ECC_HAM)
+		return 4;
+
+	/* BCH8 */
+	if (strength == FMC2_ECC_BCH8)
+		return 14;
+
+	/* BCH4 */
+	return 8;
+}
+
+NAND_ECC_CAPS_SINGLE(stm32_fmc2_ecc_caps, stm32_fmc2_calc_ecc_bytes,
+		     FMC2_ECC_STEP_SIZE,
+		     FMC2_ECC_HAM, FMC2_ECC_BCH4, FMC2_ECC_BCH8);
+
+/* FMC2 probe */
+static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2,
+				  ofnode node)
+{
+	struct stm32_fmc2_nand *nand = &fmc2->nand;
+	u32 cs[FMC2_MAX_CE];
+	int ret, i;
+
+	if (!ofnode_get_property(node, "reg", &nand->ncs))
+		return -EINVAL;
+
+	nand->ncs /= sizeof(u32);
+	if (!nand->ncs) {
+		pr_err("Invalid reg property size\n");
+		return -EINVAL;
+	}
+
+	ret = ofnode_read_u32_array(node, "reg", cs, nand->ncs);
+	if (ret < 0) {
+		pr_err("Could not retrieve reg property\n");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < nand->ncs; i++) {
+		if (cs[i] > FMC2_MAX_CE) {
+			pr_err("Invalid reg value: %d\n",
+			       nand->cs_used[i]);
+			return -EINVAL;
+		}
+
+		if (fmc2->cs_assigned & BIT(cs[i])) {
+			pr_err("Cs already assigned: %d\n",
+			       nand->cs_used[i]);
+			return -EINVAL;
+		}
+
+		fmc2->cs_assigned |= BIT(cs[i]);
+		nand->cs_used[i] = cs[i];
+	}
+
+	nand->chip.flash_node = ofnode_to_offset(node);
+
+	return 0;
+}
+
+static int stm32_fmc2_parse_dt(struct udevice *dev,
+			       struct stm32_fmc2_nfc *fmc2)
+{
+	ofnode child;
+	int ret, nchips = 0;
+
+	dev_for_each_subnode(child, dev)
+		nchips++;
+
+	if (!nchips) {
+		pr_err("NAND chip not defined\n");
+		return -EINVAL;
+	}
+
+	if (nchips > 1) {
+		pr_err("Too many NAND chips defined\n");
+		return -EINVAL;
+	}
+
+	dev_for_each_subnode(child, dev) {
+		ret = stm32_fmc2_parse_child(fmc2, child);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int stm32_fmc2_probe(struct udevice *dev)
+{
+	struct stm32_fmc2_nfc *fmc2 = dev_get_priv(dev);
+	struct stm32_fmc2_nand *nand = &fmc2->nand;
+	struct nand_chip *chip = &nand->chip;
+	struct mtd_info *mtd = &chip->mtd;
+	struct nand_ecclayout *ecclayout;
+	struct resource resource;
+	struct reset_ctl reset;
+	int oob_index, chip_cs, mem_region, ret, i;
+
+	spin_lock_init(&fmc2->controller.lock);
+	init_waitqueue_head(&fmc2->controller.wq);
+
+	ret = stm32_fmc2_parse_dt(dev, fmc2);
+	if (ret)
+		return ret;
+
+	/* Get resources */
+	ret = dev_read_resource(dev, 0, &resource);
+	if (ret) {
+		pr_err("Resource io_base not found");
+		return ret;
+	}
+	fmc2->io_base = (void __iomem *)resource.start;
+
+	for (chip_cs = 0, mem_region = 1; chip_cs < FMC2_MAX_CE;
+	     chip_cs++, mem_region += 3) {
+		if (!(fmc2->cs_assigned & BIT(chip_cs)))
+			continue;
+
+		ret = dev_read_resource(dev, mem_region, &resource);
+		if (ret) {
+			pr_err("Resource data_base not found for cs%d",
+			       chip_cs);
+			return ret;
+		}
+		fmc2->data_base[chip_cs] = (void __iomem *)resource.start;
+
+		ret = dev_read_resource(dev, mem_region + 1, &resource);
+		if (ret) {
+			pr_err("Resource cmd_base not found for cs%d",
+			       chip_cs);
+			return ret;
+		}
+		fmc2->cmd_base[chip_cs] = (void __iomem *)resource.start;
+
+		ret = dev_read_resource(dev, mem_region + 2, &resource);
+		if (ret) {
+			pr_err("Resource addr_base not found for cs%d",
+			       chip_cs);
+			return ret;
+		}
+		fmc2->addr_base[chip_cs] = (void __iomem *)resource.start;
+	}
+
+	/* Enable the clock */
+	ret = clk_get_by_index(dev, 0, &fmc2->clk);
+	if (ret)
+		return ret;
+
+	ret = clk_enable(&fmc2->clk);
+	if (ret)
+		return ret;
+
+	/* Reset */
+	ret = reset_get_by_index(dev, 0, &reset);
+	if (!ret) {
+		reset_assert(&reset);
+		udelay(2);
+		reset_deassert(&reset);
+	}
+
+	/* FMC2 init routine */
+	stm32_fmc2_init(fmc2);
+
+	chip->controller = &fmc2->base;
+	chip->select_chip = stm32_fmc2_select_chip;
+	chip->setup_data_interface = stm32_fmc2_setup_interface;
+	chip->cmd_ctrl = stm32_fmc2_cmd_ctrl;
+	chip->chip_delay = FMC2_RB_DELAY_US;
+	chip->options |= NAND_BUSWIDTH_AUTO | NAND_NO_SUBPAGE_WRITE |
+			 NAND_USE_BOUNCE_BUFFER;
+
+	/* Default ECC settings */
+	chip->ecc.mode = NAND_ECC_HW;
+	chip->ecc.size = FMC2_ECC_STEP_SIZE;
+	chip->ecc.strength = FMC2_ECC_BCH8;
+
+	/* Scan to find existence of the device */
+	ret = nand_scan_ident(mtd, nand->ncs, NULL);
+	if (ret)
+		return ret;
+
+	/*
+	 * Only NAND_ECC_HW mode is actually supported
+	 * Hamming => ecc.strength = 1
+	 * BCH4 => ecc.strength = 4
+	 * BCH8 => ecc.strength = 8
+	 * ECC sector size = 512
+	 */
+	if (chip->ecc.mode != NAND_ECC_HW) {
+		pr_err("Nand_ecc_mode is not well defined in the DT\n");
+		return -EINVAL;
+	}
+
+	ret = nand_check_ecc_caps(chip, &stm32_fmc2_ecc_caps,
+				  mtd->oobsize - FMC2_BBM_LEN);
+	if (ret) {
+		pr_err("No valid ECC settings set\n");
+		return ret;
+	}
+
+	if (chip->bbt_options & NAND_BBT_USE_FLASH)
+		chip->bbt_options |= NAND_BBT_NO_OOB;
+
+	/* NAND callbacks setup */
+	stm32_fmc2_nand_callbacks_setup(chip);
+
+	/* Define ECC layout */
+	ecclayout = &fmc2->ecclayout;
+	ecclayout->eccbytes = chip->ecc.bytes *
+			      (mtd->writesize / chip->ecc.size);
+	oob_index = FMC2_BBM_LEN;
+	for (i = 0; i < ecclayout->eccbytes; i++, oob_index++)
+		ecclayout->eccpos[i] = oob_index;
+	ecclayout->oobfree->offset = oob_index;
+	ecclayout->oobfree->length = mtd->oobsize - ecclayout->oobfree->offset;
+	chip->ecc.layout = ecclayout;
+
+	/* Configure bus width to 16-bit */
+	if (chip->options & NAND_BUSWIDTH_16)
+		stm32_fmc2_set_buswidth_16(fmc2, true);
+
+	/* Scan the device to fill MTD data-structures */
+	ret = nand_scan_tail(mtd);
+	if (ret)
+		return ret;
+
+	return nand_register(0, mtd);
+}
+
+static const struct udevice_id stm32_fmc2_match[] = {
+	{ .compatible = "st,stm32mp15-fmc2" },
+	{ /* Sentinel */ }
+};
+
+U_BOOT_DRIVER(stm32_fmc2_nand) = {
+	.name = "stm32_fmc2_nand",
+	.id = UCLASS_MTD,
+	.of_match = stm32_fmc2_match,
+	.probe = stm32_fmc2_probe,
+	.priv_auto_alloc_size = sizeof(struct stm32_fmc2_nfc),
+};
+
+void board_nand_init(void)
+{
+	struct udevice *dev;
+	int ret;
+
+	ret = uclass_get_device_by_driver(UCLASS_MTD,
+					  DM_GET_DRIVER(stm32_fmc2_nand),
+					  &dev);
+	if (ret && ret != -ENODEV)
+		pr_err("Failed to initialize STM32 FMC2 NAND controller. (error %d)\n",
+		       ret);
+}
diff --git a/drivers/mtd/nand/spi/gigadevice.c b/drivers/mtd/nand/spi/gigadevice.c
index 0bade20..3681c5e 100644
--- a/drivers/mtd/nand/spi/gigadevice.c
+++ b/drivers/mtd/nand/spi/gigadevice.c
@@ -12,12 +12,11 @@
 #endif
 #include <linux/mtd/spinand.h>
 
-#define SPINAND_MFR_GIGADEVICE			0xc8
+#define SPINAND_MFR_GIGADEVICE			0xC8
+#define GD5FXGQ4XA_STATUS_ECC_1_7_BITFLIPS	(1 << 4)
+#define GD5FXGQ4XA_STATUS_ECC_8_BITFLIPS	(3 << 4)
 
-#define GIGADEVICE_STATUS_ECC_MASK		GENMASK(5, 4)
-#define GIGADEVICE_STATUS_ECC_NO_BITFLIPS	(0 << 4)
-#define GIGADEVICE_STATUS_ECC_1TO7_BITFLIPS	(1 << 4)
-#define GIGADEVICE_STATUS_ECC_8_BITFLIPS	(3 << 4)
+#define GD5FXGQ4XEXXG_REG_STATUS2		0xf0
 
 static SPINAND_OP_VARIANTS(read_cache_variants,
 		SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0),
@@ -35,8 +34,8 @@
 		SPINAND_PROG_LOAD_X4(false, 0, NULL, 0),
 		SPINAND_PROG_LOAD(false, 0, NULL, 0));
 
-static int gd5f1gq4u_ooblayout_ecc(struct mtd_info *mtd, int section,
-				   struct mtd_oob_region *region)
+static int gd5fxgq4xexxg_ooblayout_ecc(struct mtd_info *mtd, int section,
+				       struct mtd_oob_region *region)
 {
 	if (section)
 		return -ERANGE;
@@ -47,38 +46,49 @@
 	return 0;
 }
 
-static int gd5f1gq4u_ooblayout_free(struct mtd_info *mtd, int section,
-				    struct mtd_oob_region *region)
+static int gd5fxgq4xexxg_ooblayout_free(struct mtd_info *mtd, int section,
+					struct mtd_oob_region *region)
 {
 	if (section)
 		return -ERANGE;
 
-	/* Reserve 2 bytes for the BBM. */
-	region->offset = 2;
-	region->length = 62;
+	/* Reserve 1 bytes for the BBM. */
+	region->offset = 1;
+	region->length = 63;
 
 	return 0;
 }
 
-static const struct mtd_ooblayout_ops gd5f1gq4u_ooblayout = {
-	.ecc = gd5f1gq4u_ooblayout_ecc,
-	.free = gd5f1gq4u_ooblayout_free,
-};
-
-static int gd5f1gq4u_ecc_get_status(struct spinand_device *spinand,
-				    u8 status)
+static int gd5fxgq4xexxg_ecc_get_status(struct spinand_device *spinand,
+					u8 status)
 {
-	if (status)
-		debug("%s (%d): status=%02x\n", __func__, __LINE__, status);
+	u8 status2;
+	struct spi_mem_op op = SPINAND_GET_FEATURE_OP(GD5FXGQ4XEXXG_REG_STATUS2,
+						      &status2);
+	int ret;
 
-	switch (status & GIGADEVICE_STATUS_ECC_MASK) {
+	switch (status & STATUS_ECC_MASK) {
 	case STATUS_ECC_NO_BITFLIPS:
 		return 0;
 
-	case GIGADEVICE_STATUS_ECC_1TO7_BITFLIPS:
-		return 7;
+	case GD5FXGQ4XA_STATUS_ECC_1_7_BITFLIPS:
+		/*
+		 * Read status2 register to determine a more fine grained
+		 * bit error status
+		 */
+		ret = spi_mem_exec_op(spinand->slave, &op);
+		if (ret)
+			return ret;
 
-	case GIGADEVICE_STATUS_ECC_8_BITFLIPS:
+		/*
+		 * 4 ... 7 bits are flipped (1..4 can't be detected, so
+		 * report the maximum of 4 in this case
+		 */
+		/* bits sorted this way (3...0): ECCS1,ECCS0,ECCSE1,ECCSE0 */
+		return ((status & STATUS_ECC_MASK) >> 2) |
+			((status2 & STATUS_ECC_MASK) >> 4);
+
+	case GD5FXGQ4XA_STATUS_ECC_8_BITFLIPS:
 		return 8;
 
 	case STATUS_ECC_UNCOR_ERROR:
@@ -91,16 +101,21 @@
 	return -EINVAL;
 }
 
+static const struct mtd_ooblayout_ops gd5fxgq4xexxg_ooblayout = {
+	.ecc = gd5fxgq4xexxg_ooblayout_ecc,
+	.free = gd5fxgq4xexxg_ooblayout_free,
+};
+
 static const struct spinand_info gigadevice_spinand_table[] = {
-	SPINAND_INFO("GD5F1GQ4UC", 0xd1,
+	SPINAND_INFO("GD5F1GQ4UExxG", 0xd1,
 		     NAND_MEMORG(1, 2048, 128, 64, 1024, 1, 1, 1),
-		     NAND_ECCREQ(8, 2048),
+		     NAND_ECCREQ(8, 512),
 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
 					      &write_cache_variants,
 					      &update_cache_variants),
 		     0,
-		     SPINAND_ECCINFO(&gd5f1gq4u_ooblayout,
-				     gd5f1gq4u_ecc_get_status)),
+		     SPINAND_ECCINFO(&gd5fxgq4xexxg_ooblayout,
+				     gd5fxgq4xexxg_ecc_get_status)),
 };
 
 static int gigadevice_spinand_detect(struct spinand_device *spinand)
@@ -109,8 +124,8 @@
 	int ret;
 
 	/*
-	 * Gigadevice SPI NAND read ID need a dummy byte,
-	 * so the first byte in raw_id is dummy.
+	 * For GD NANDs, There is an address byte needed to shift in before IDs
+	 * are read out, so the first byte in raw_id is dummy.
 	 */
 	if (id[1] != SPINAND_MFR_GIGADEVICE)
 		return 0;
diff --git a/drivers/mtd/spi/Kconfig b/drivers/mtd/spi/Kconfig
index 5671bca..d3b007a 100644
--- a/drivers/mtd/spi/Kconfig
+++ b/drivers/mtd/spi/Kconfig
@@ -62,6 +62,9 @@
 	  The default mode may be provided by the platform
 	  to handle the common case when only a single serial
 	  flash is present on the system.
+	  Not used for boot with device tree; the SPI driver reads
+	  speed and mode from platdata values computed from
+	  available node.
 
 config SF_DEFAULT_SPEED
 	int "SPI Flash default speed in Hz"
@@ -71,6 +74,9 @@
 	  The default speed may be provided by the platform
 	  to handle the common case when only a single serial
 	  flash is present on the system.
+	  Not used for boot with device tree; the SPI driver reads
+	  speed and mode from platdata values computed from
+	  available node.
 
 if SPI_FLASH
 
diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c
index 7f1378f..73297e1 100644
--- a/drivers/mtd/spi/sf_probe.c
+++ b/drivers/mtd/spi/sf_probe.c
@@ -166,7 +166,6 @@
 };
 
 static const struct udevice_id spi_flash_std_ids[] = {
-	{ .compatible = "spi-flash" },
 	{ .compatible = "jedec,spi-nor" },
 	{ }
 };
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
index b7f0733..c4e2f6a 100644
--- a/drivers/mtd/spi/spi-nor-core.c
+++ b/drivers/mtd/spi/spi-nor-core.c
@@ -524,8 +524,11 @@
  */
 static int spi_nor_erase_sector(struct spi_nor *nor, u32 addr)
 {
-	u8 buf[SPI_NOR_MAX_ADDR_WIDTH];
-	int i;
+	struct spi_mem_op op =
+		SPI_MEM_OP(SPI_MEM_OP_CMD(nor->erase_opcode, 1),
+			   SPI_MEM_OP_ADDR(nor->addr_width, addr, 1),
+			   SPI_MEM_OP_NO_DUMMY,
+			   SPI_MEM_OP_NO_DATA);
 
 	if (nor->erase)
 		return nor->erase(nor, addr);
@@ -534,12 +537,7 @@
 	 * Default implementation, if driver doesn't have a specialized HW
 	 * control
 	 */
-	for (i = nor->addr_width - 1; i >= 0; i--) {
-		buf[i] = addr & 0xff;
-		addr >>= 8;
-	}
-
-	return nor->write_reg(nor, nor->erase_opcode, buf, nor->addr_width);
+	return spi_mem_exec_op(nor->spi, &op);
 }
 
 /*
diff --git a/drivers/mtd/spi/spi-nor-ids.c b/drivers/mtd/spi/spi-nor-ids.c
index 3215e24..ec92976 100644
--- a/drivers/mtd/spi/spi-nor-ids.c
+++ b/drivers/mtd/spi/spi-nor-ids.c
@@ -106,6 +106,11 @@
 			SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
 			SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
 	},
+	{
+		INFO("gd25lq128", 0xc86018, 0, 64 * 1024, 256,
+			SECT_4K | SPI_NOR_DUAL_READ |
+			SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
+	},
 #endif
 #ifdef CONFIG_SPI_FLASH_ISSI		/* ISSI */
 	/* ISSI */
@@ -142,6 +147,7 @@
 	{ INFO("mx25l25655e", 0xc22619, 0, 64 * 1024, 512, 0) },
 	{ INFO("mx66l51235l", 0xc2201a, 0, 64 * 1024, 1024, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
 	{ INFO("mx66u51235f", 0xc2253a, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
+	{ INFO("mx66u2g45g",  0xc2253c, 0, 64 * 1024, 4096, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
 	{ INFO("mx66l1g45g",  0xc2201b, 0, 64 * 1024, 2048, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
 	{ INFO("mx25l1633e", 0xc22415, 0, 64 * 1024,   32, SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES | SECT_4K) },
 #endif
@@ -187,6 +193,7 @@
 	{ INFO("s25fl116k",  0x014015,      0,  64 * 1024,  32, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
 	{ INFO("s25fl164k",  0x014017,      0,  64 * 1024, 128, SECT_4K) },
 	{ INFO("s25fl208k",  0x014014,      0,  64 * 1024,  16, SECT_4K | SPI_NOR_DUAL_READ) },
+	{ INFO("s25fl064l",  0x016017,      0,  64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
 	{ INFO("s25fl128l",  0x016018,      0,  64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
 #endif
 #ifdef CONFIG_SPI_FLASH_SST		/* SST */
diff --git a/drivers/net/ag7xxx.c b/drivers/net/ag7xxx.c
index 8146c31..7f1dee4 100644
--- a/drivers/net/ag7xxx.c
+++ b/drivers/net/ag7xxx.c
@@ -3,6 +3,7 @@
  * Atheros AR71xx / AR9xxx GMAC driver
  *
  * Copyright (C) 2016 Marek Vasut <marex@denx.de>
+ * Copyright (C) 2019 Rosy Song <rosysong@rosinson.com>
  */
 
 #include <common.h>
@@ -23,6 +24,8 @@
 enum ag7xxx_model {
 	AG7XXX_MODEL_AG933X,
 	AG7XXX_MODEL_AG934X,
+	AG7XXX_MODEL_AG953X,
+	AG7XXX_MODEL_AG956X
 };
 
 /* MAC Configuration 1 */
@@ -99,8 +102,29 @@
 /* Rx Status */
 #define AG7XXX_ETH_DMA_RX_STATUS		0x194
 
+/* Custom register at 0x1805002C */
+#define AG7XXX_ETH_XMII			0x2C
+#define AG7XXX_ETH_XMII_TX_INVERT		BIT(31)
+#define AG7XXX_ETH_XMII_RX_DELAY_LSB		28
+#define AG7XXX_ETH_XMII_RX_DELAY_MASK		0x30000000
+#define AG7XXX_ETH_XMII_RX_DELAY_SET(x) \
+	(((x) << AG7XXX_ETH_XMII_RX_DELAY_LSB) & AG7XXX_ETH_XMII_RX_DELAY_MASK)
+#define AG7XXX_ETH_XMII_TX_DELAY_LSB		26
+#define AG7XXX_ETH_XMII_TX_DELAY_MASK		0x0c000000
+#define AG7XXX_ETH_XMII_TX_DELAY_SET(x) \
+	(((x) << AG7XXX_ETH_XMII_TX_DELAY_LSB) & AG7XXX_ETH_XMII_TX_DELAY_MASK)
+#define AG7XXX_ETH_XMII_GIGE		BIT(25)
+
 /* Custom register at 0x18070000 */
 #define AG7XXX_GMAC_ETH_CFG			0x00
+#define AG7XXX_ETH_CFG_RXDV_DELAY_LSB		16
+#define AG7XXX_ETH_CFG_RXDV_DELAY_MASK		0x00030000
+#define AG7XXX_ETH_CFG_RXDV_DELAY_SET(x) \
+	(((x) << AG7XXX_ETH_CFG_RXDV_DELAY_LSB) & AG7XXX_ETH_CFG_RXDV_DELAY_MASK)
+#define AG7XXX_ETH_CFG_RXD_DELAY_LSB		14
+#define AG7XXX_ETH_CFG_RXD_DELAY_MASK		0x0000c000
+#define AG7XXX_ETH_CFG_RXD_DELAY_SET(x)	\
+	(((x) << AG7XXX_ETH_CFG_RXD_DELAY_LSB) & AG7XXX_ETH_CFG_RXD_DELAY_MASK)
 #define AG7XXX_ETH_CFG_SW_PHY_ADDR_SWAP		BIT(8)
 #define AG7XXX_ETH_CFG_SW_PHY_SWAP		BIT(7)
 #define AG7XXX_ETH_CFG_SW_ONLY_MODE		BIT(6)
@@ -197,24 +221,33 @@
 	u32 reg_addr;
 	u32 phy_temp;
 	u32 reg_temp;
+	u32 reg_temp_w = (reg & 0xfffffffc) >> 1;
 	u16 rv = 0;
 	int ret;
 
-	if (priv->model == AG7XXX_MODEL_AG933X) {
+	if (priv->model == AG7XXX_MODEL_AG933X ||
+	    priv->model == AG7XXX_MODEL_AG953X) {
 		phy_addr = 0x1f;
 		reg_addr = 0x10;
-	} else if (priv->model == AG7XXX_MODEL_AG934X) {
+	} else if (priv->model == AG7XXX_MODEL_AG934X ||
+		   priv->model == AG7XXX_MODEL_AG956X) {
 		phy_addr = 0x18;
 		reg_addr = 0x00;
 	} else
 		return -EINVAL;
 
-	ret = ag7xxx_switch_write(bus, phy_addr, reg_addr, reg >> 9);
+	if (priv->model == AG7XXX_MODEL_AG956X)
+		ret = ag7xxx_switch_write(bus, phy_addr, reg_addr, (reg >> 9) & 0x1ff);
+	else
+		ret = ag7xxx_switch_write(bus, phy_addr, reg_addr, reg >> 9);
 	if (ret)
 		return ret;
 
 	phy_temp = ((reg >> 6) & 0x7) | 0x10;
-	reg_temp = (reg >> 1) & 0x1e;
+	if (priv->model == AG7XXX_MODEL_AG956X)
+		reg_temp = reg_temp_w & 0x1f;
+	else
+		reg_temp = (reg >> 1) & 0x1e;
 	*val = 0;
 
 	ret = ag7xxx_switch_read(bus, phy_temp, reg_temp | 0, &rv);
@@ -222,7 +255,13 @@
 		return ret;
 	*val |= rv;
 
-	ret = ag7xxx_switch_read(bus, phy_temp, reg_temp | 1, &rv);
+	if (priv->model == AG7XXX_MODEL_AG956X) {
+		phy_temp = (((reg_temp_w + 1) >> 5) & 0x7) | 0x10;
+		reg_temp = (reg_temp_w + 1) & 0x1f;
+		ret = ag7xxx_switch_read(bus, phy_temp, reg_temp, &rv);
+	} else {
+		ret = ag7xxx_switch_read(bus, phy_temp, reg_temp | 1, &rv);
+	}
 	if (ret < 0)
 		return ret;
 	*val |= (rv << 16);
@@ -237,23 +276,34 @@
 	u32 reg_addr;
 	u32 phy_temp;
 	u32 reg_temp;
+	u32 reg_temp_w = (reg & 0xfffffffc) >> 1;
 	int ret;
 
-	if (priv->model == AG7XXX_MODEL_AG933X) {
+	if (priv->model == AG7XXX_MODEL_AG933X ||
+	    priv->model == AG7XXX_MODEL_AG953X) {
 		phy_addr = 0x1f;
 		reg_addr = 0x10;
-	} else if (priv->model == AG7XXX_MODEL_AG934X) {
+	} else if (priv->model == AG7XXX_MODEL_AG934X ||
+		   priv->model == AG7XXX_MODEL_AG956X) {
 		phy_addr = 0x18;
 		reg_addr = 0x00;
 	} else
 		return -EINVAL;
 
-	ret = ag7xxx_switch_write(bus, phy_addr, reg_addr, reg >> 9);
+	if (priv->model == AG7XXX_MODEL_AG956X)
+		ret = ag7xxx_switch_write(bus, phy_addr, reg_addr, (reg >> 9) & 0x1ff);
+	else
+		ret = ag7xxx_switch_write(bus, phy_addr, reg_addr, reg >> 9);
 	if (ret)
 		return ret;
 
-	phy_temp = ((reg >> 6) & 0x7) | 0x10;
-	reg_temp = (reg >> 1) & 0x1e;
+	if (priv->model == AG7XXX_MODEL_AG956X) {
+		reg_temp = (reg_temp_w + 1) & 0x1f;
+		phy_temp = (((reg_temp_w + 1) >> 5) & 0x7) | 0x10;
+	} else {
+		phy_temp = ((reg >> 6) & 0x7) | 0x10;
+		reg_temp = (reg >> 1) & 0x1e;
+	}
 
 	/*
 	 * The switch on AR933x has some special register behavior, which
@@ -272,10 +322,18 @@
 		if (ret < 0)
 			return ret;
 	} else {
-		ret = ag7xxx_switch_write(bus, phy_temp, reg_temp | 1, val >> 16);
+		if (priv->model == AG7XXX_MODEL_AG956X)
+			ret = ag7xxx_switch_write(bus, phy_temp, reg_temp, val >> 16);
+		else
+			ret = ag7xxx_switch_write(bus, phy_temp, reg_temp | 1, val >> 16);
 		if (ret < 0)
 			return ret;
 
+		if (priv->model == AG7XXX_MODEL_AG956X) {
+			phy_temp = ((reg_temp_w >> 5) & 0x7) | 0x10;
+			reg_temp = reg_temp_w & 0x1f;
+		}
+
 		ret = ag7xxx_switch_write(bus, phy_temp, reg_temp | 0, val & 0xffff);
 		if (ret < 0)
 			return ret;
@@ -598,10 +656,19 @@
 			return 0;
 	}
 
-	if (priv->model == AG7XXX_MODEL_AG934X) {
-		writel(AG7XXX_ETH_MII_MGMT_CFG_RESET | 0x4,
+	if (priv->model == AG7XXX_MODEL_AG934X)
+		reg = 0x4;
+	else if (priv->model == AG7XXX_MODEL_AG953X)
+		reg = 0x2;
+	else if (priv->model == AG7XXX_MODEL_AG956X)
+		reg = 0x7;
+
+	if (priv->model == AG7XXX_MODEL_AG934X ||
+	    priv->model == AG7XXX_MODEL_AG953X ||
+	    priv->model == AG7XXX_MODEL_AG956X) {
+		writel(AG7XXX_ETH_MII_MGMT_CFG_RESET | reg,
 		       priv->regs + AG7XXX_ETH_MII_MGMT_CFG);
-		writel(0x4, priv->regs + AG7XXX_ETH_MII_MGMT_CFG);
+		writel(reg, priv->regs + AG7XXX_ETH_MII_MGMT_CFG);
 		return 0;
 	}
 
@@ -695,6 +762,112 @@
 	if (ret)
 		return ret;
 
+	return 0;
+}
+
+static int ag953x_phy_setup_wan(struct udevice *dev)
+{
+	int ret;
+	u32 reg = 0;
+	struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
+
+	/* Set wan port connect to GE0 */
+	ret = ag7xxx_switch_reg_read(priv->bus, 0x8, &reg);
+	if (ret)
+		return ret;
+
+	ret = ag7xxx_switch_reg_write(priv->bus, 0x8, reg | BIT(28));
+	if (ret)
+		return ret;
+
+	/* Configure switch port 4 (GMAC0) */
+	ret = ag7xxx_switch_write(priv->bus, 4, MII_BMCR, 0x9000);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int ag953x_phy_setup_lan(struct udevice *dev)
+{
+	struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
+	int i, ret;
+	u32 reg = 0;
+
+	/* Reset the switch */
+	ret = ag7xxx_switch_reg_read(priv->bus, 0, &reg);
+	if (ret)
+		return ret;
+
+	ret = ag7xxx_switch_reg_write(priv->bus, 0, reg | BIT(31));
+	if (ret)
+		return ret;
+
+	do {
+		ret = ag7xxx_switch_reg_read(priv->bus, 0, &reg);
+		if (ret)
+			return ret;
+	} while (reg & BIT(31));
+
+	ret = ag7xxx_switch_reg_write(priv->bus, 0x100, 0x4e);
+	if (ret)
+		return ret;
+
+	/* Set GMII mode */
+	ret = ag7xxx_switch_reg_read(priv->bus, 0x4, &reg);
+	if (ret)
+		return ret;
+
+	ret = ag7xxx_switch_reg_write(priv->bus, 0x4, reg | BIT(6));
+	if (ret)
+		return ret;
+
+	/* Configure switch ports 0...4 (GMAC1) */
+	for (i = 0; i < 5; i++) {
+		ret = ag7xxx_switch_write(priv->bus, i, MII_BMCR, 0x9000);
+		if (ret)
+			return ret;
+	}
+
+	for (i = 0; i < 5; i++) {
+		ret = ag7xxx_switch_reg_write(priv->bus, (i + 2) * 0x100, BIT(9));
+		if (ret)
+			return ret;
+	}
+
+	/* QM Control */
+	ret = ag7xxx_switch_reg_write(priv->bus, 0x38, 0xc000050e);
+	if (ret)
+		return ret;
+
+	/* Disable Atheros header */
+	ret = ag7xxx_switch_reg_write(priv->bus, 0x104, 0x4004);
+	if (ret)
+		return ret;
+
+	/* Tag priority mapping */
+	ret = ag7xxx_switch_reg_write(priv->bus, 0x70, 0xfa50);
+	if (ret)
+		return ret;
+
+	/* Enable ARP packets to the CPU */
+	ret = ag7xxx_switch_reg_read(priv->bus, 0x5c, &reg);
+	if (ret)
+		return ret;
+
+	ret = ag7xxx_switch_reg_write(priv->bus, 0x5c, reg | 0x100000);
+	if (ret)
+		return ret;
+
+	/* Enable broadcast packets to the CPU */
+	ret = ag7xxx_switch_reg_read(priv->bus, 0x2c, &reg);
+	if (ret)
+		return ret;
+
+	ret = ag7xxx_switch_reg_write(priv->bus, 0x2c, reg | BIT(25) | BIT(26));
+	if (ret)
+		return ret;
+
 	return 0;
 }
 
@@ -703,9 +876,15 @@
 	struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
 	int ret;
 
-	ret = ag7xxx_mdio_write(priv->bus, port, 0, MII_ADVERTISE,
-				ADVERTISE_ALL | ADVERTISE_PAUSE_CAP |
-				ADVERTISE_PAUSE_ASYM);
+	if (priv->model == AG7XXX_MODEL_AG953X ||
+	    priv->model == AG7XXX_MODEL_AG956X) {
+		ret = ag7xxx_switch_write(priv->bus, port, MII_ADVERTISE,
+					ADVERTISE_ALL);
+	} else {
+		ret = ag7xxx_mdio_write(priv->bus, port, 0, MII_ADVERTISE,
+					ADVERTISE_ALL | ADVERTISE_PAUSE_CAP |
+					ADVERTISE_PAUSE_ASYM);
+	}
 	if (ret)
 		return ret;
 
@@ -714,8 +893,18 @@
 					ADVERTISE_1000FULL);
 		if (ret)
 			return ret;
+	} else if (priv->model == AG7XXX_MODEL_AG956X) {
+		ret = ag7xxx_switch_write(priv->bus, port, MII_CTRL1000,
+					  ADVERTISE_1000FULL);
+		if (ret)
+			return ret;
 	}
 
+	if (priv->model == AG7XXX_MODEL_AG953X ||
+	    priv->model == AG7XXX_MODEL_AG956X)
+		return ag7xxx_switch_write(priv->bus, port, MII_BMCR,
+					 BMCR_ANENABLE | BMCR_RESET);
+
 	return ag7xxx_mdio_write(priv->bus, port, 0, MII_BMCR,
 				 BMCR_ANENABLE | BMCR_RESET);
 }
@@ -724,13 +913,24 @@
 {
 	struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
 	int ret;
+	u16 reg;
 
-	do {
-		ret = ag7xxx_mdio_read(priv->bus, port, 0, MII_BMCR);
-		if (ret < 0)
-			return ret;
-		mdelay(10);
-	} while (ret & BMCR_RESET);
+	if (priv->model == AG7XXX_MODEL_AG953X ||
+	    priv->model == AG7XXX_MODEL_AG956X) {
+		do {
+			ret = ag7xxx_switch_read(priv->bus, port, MII_BMCR, &reg);
+			if (ret < 0)
+				return ret;
+			mdelay(10);
+		} while (reg & BMCR_RESET);
+	} else {
+		do {
+			ret = ag7xxx_mdio_read(priv->bus, port, 0, MII_BMCR);
+			if (ret < 0)
+				return ret;
+			mdelay(10);
+		} while (ret & BMCR_RESET);
+	}
 
 	return 0;
 }
@@ -739,10 +939,13 @@
 {
 	struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
 	int i, ret, phymax;
+	u16 reg;
 
 	if (priv->model == AG7XXX_MODEL_AG933X)
 		phymax = 4;
-	else if (priv->model == AG7XXX_MODEL_AG934X)
+	else if (priv->model == AG7XXX_MODEL_AG934X ||
+		priv->model == AG7XXX_MODEL_AG953X ||
+		priv->model == AG7XXX_MODEL_AG956X)
 		phymax = 5;
 	else
 		return -EINVAL;
@@ -757,7 +960,10 @@
 			return ret;
 
 		/* Read out link status */
-		ret = ag7xxx_mdio_read(priv->bus, phymax, 0, MII_MIPSCR);
+		if (priv->model == AG7XXX_MODEL_AG953X)
+			ret = ag7xxx_switch_read(priv->bus, phymax, MII_MIPSCR, &reg);
+		else
+			ret = ag7xxx_mdio_read(priv->bus, phymax, 0, MII_MIPSCR);
 		if (ret < 0)
 			return ret;
 
@@ -779,7 +985,11 @@
 
 	for (i = 0; i < phymax; i++) {
 		/* Read out link status */
-		ret = ag7xxx_mdio_read(priv->bus, i, 0, MII_MIPSCR);
+		if (priv->model == AG7XXX_MODEL_AG953X ||
+		    priv->model == AG7XXX_MODEL_AG956X)
+			ret = ag7xxx_switch_read(priv->bus, i, MII_MIPSCR, &reg);
+		else
+			ret = ag7xxx_mdio_read(priv->bus, i, 0, MII_MIPSCR);
 		if (ret < 0)
 			return ret;
 	}
@@ -837,6 +1047,63 @@
 	ret = ag7xxx_switch_reg_write(priv->bus, 0x66c, reg);
 	if (ret)
 		return ret;
+
+	return 0;
+}
+
+static int ag956x_phy_setup(struct udevice *dev)
+{
+	struct ar7xxx_eth_priv *priv = dev_get_priv(dev);
+	int i, ret;
+	u32 reg, ctrl;
+
+	ret = ag7xxx_switch_reg_read(priv->bus, 0x0, &reg);
+	if (ret)
+		return ret;
+	if ((reg & 0xffff) >= 0x1301)
+		ctrl = 0xc74164de;
+	else
+		ctrl = 0xc74164d0;
+
+	ret = ag7xxx_switch_reg_write(priv->bus, 0x4, BIT(7));
+	if (ret)
+		return ret;
+
+	ret = ag7xxx_switch_reg_write(priv->bus, 0xe0, ctrl);
+	if (ret)
+		return ret;
+
+	ret = ag7xxx_switch_reg_write(priv->bus, 0x624, 0x7f7f7f7f);
+	if (ret)
+		return ret;
+
+	/*
+	 * Values suggested by the switch team when s17 in sgmii
+	 * configuration. 0x10(S17_PWS_REG) = 0x602613a0
+	 */
+	ret = ag7xxx_switch_reg_write(priv->bus, 0x10, 0x602613a0);
+	if (ret)
+		return ret;
+
+	ret = ag7xxx_switch_reg_write(priv->bus, 0x7c, 0x0000007e);
+	if (ret)
+		return ret;
+
+	/* AR8337/AR8334 v1.0 fixup */
+	ret = ag7xxx_switch_reg_read(priv->bus, 0, &reg);
+	if (ret)
+		return ret;
+	if ((reg & 0xffff) == 0x1301) {
+		for (i = 0; i < 5; i++) {
+			/* Turn on Gigabit clock */
+			ret = ag7xxx_switch_write(priv->bus, i, 0x1d, 0x3d);
+			if (ret)
+				return ret;
+			ret = ag7xxx_switch_write(priv->bus, i, 0x1e, 0x6820);
+			if (ret)
+				return ret;
+		}
+	}
 
 	return 0;
 }
@@ -858,8 +1125,15 @@
 			ret = ag933x_phy_setup_wan(dev);
 		else
 			ret = ag933x_phy_setup_lan(dev);
+	} else if (priv->model == AG7XXX_MODEL_AG953X) {
+		if (priv->interface == PHY_INTERFACE_MODE_RMII)
+			ret = ag953x_phy_setup_wan(dev);
+		else
+			ret = ag953x_phy_setup_lan(dev);
 	} else if (priv->model == AG7XXX_MODEL_AG934X) {
 		ret = ag934x_phy_setup(dev);
+	} else if (priv->model == AG7XXX_MODEL_AG956X) {
+		ret = ag956x_phy_setup(dev);
 	} else {
 		return -EINVAL;
 	}
@@ -997,6 +1271,8 @@
 static const struct udevice_id ag7xxx_eth_ids[] = {
 	{ .compatible = "qca,ag933x-mac", .data = AG7XXX_MODEL_AG933X },
 	{ .compatible = "qca,ag934x-mac", .data = AG7XXX_MODEL_AG934X },
+	{ .compatible = "qca,ag953x-mac", .data = AG7XXX_MODEL_AG953X },
+	{ .compatible = "qca,ag956x-mac", .data = AG7XXX_MODEL_AG956X },
 	{ }
 };
 
diff --git a/drivers/net/mscc_eswitch/Kconfig b/drivers/net/mscc_eswitch/Kconfig
index 88e5a97..6359d0b 100644
--- a/drivers/net/mscc_eswitch/Kconfig
+++ b/drivers/net/mscc_eswitch/Kconfig
@@ -15,3 +15,17 @@
 	select PHYLIB
 	help
 	  This driver supports the Luton network switch device.
+
+config MSCC_JR2_SWITCH
+	bool "Jaguar2 switch driver"
+	depends on DM_ETH && ARCH_MSCC
+	select PHYLIB
+	help
+	  This driver supports the Jaguar2 network switch device.
+
+config MSCC_SERVALT_SWITCH
+	bool "Servalt switch driver"
+	depends on DM_ETH && ARCH_MSCC
+	select PHYLIB
+	help
+	  This driver supports the Servalt network switch device.
diff --git a/drivers/net/mscc_eswitch/Makefile b/drivers/net/mscc_eswitch/Makefile
index 751a839..bffd8ec 100644
--- a/drivers/net/mscc_eswitch/Makefile
+++ b/drivers/net/mscc_eswitch/Makefile
@@ -1,3 +1,5 @@
 
 obj-$(CONFIG_MSCC_OCELOT_SWITCH) += ocelot_switch.o mscc_miim.o mscc_xfer.o mscc_mac_table.o
 obj-$(CONFIG_MSCC_LUTON_SWITCH) += luton_switch.o mscc_miim.o mscc_xfer.o mscc_mac_table.o
+obj-$(CONFIG_MSCC_JR2_SWITCH) += jr2_switch.o mscc_xfer.o
+obj-$(CONFIG_MSCC_SERVALT_SWITCH) += servalt_switch.o mscc_xfer.o
diff --git a/drivers/net/mscc_eswitch/jr2_switch.c b/drivers/net/mscc_eswitch/jr2_switch.c
new file mode 100644
index 0000000..60d408f
--- /dev/null
+++ b/drivers/net/mscc_eswitch/jr2_switch.c
@@ -0,0 +1,1075 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+#include <common.h>
+#include <config.h>
+#include <dm.h>
+#include <dm/of_access.h>
+#include <dm/of_addr.h>
+#include <fdt_support.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <miiphy.h>
+#include <net.h>
+#include <wait_bit.h>
+
+#include <dt-bindings/mscc/jr2_data.h>
+#include "mscc_xfer.h"
+
+#define GCB_MIIM_MII_STATUS		0x0
+#define		GCB_MIIM_STAT_BUSY		BIT(3)
+#define GCB_MIIM_MII_CMD		0x8
+#define		GCB_MIIM_MII_CMD_SCAN		BIT(0)
+#define		GCB_MIIM_MII_CMD_OPR_WRITE	BIT(1)
+#define		GCB_MIIM_MII_CMD_OPR_READ	BIT(2)
+#define		GCB_MIIM_MII_CMD_SINGLE_SCAN	BIT(3)
+#define		GCB_MIIM_MII_CMD_WRDATA(x)	((x) << 4)
+#define		GCB_MIIM_MII_CMD_REGAD(x)	((x) << 20)
+#define		GCB_MIIM_MII_CMD_PHYAD(x)	((x) << 25)
+#define		GCB_MIIM_MII_CMD_VLD		BIT(31)
+#define GCB_MIIM_DATA			0xC
+#define		GCB_MIIM_DATA_ERROR		(0x3 << 16)
+
+#define ANA_AC_RAM_CTRL_RAM_INIT		0x94358
+#define ANA_AC_STAT_GLOBAL_CFG_PORT_RESET	0x94370
+
+#define ANA_CL_PORT_VLAN_CFG(x)			(0x24018 + 0xc8 * (x))
+#define		ANA_CL_PORT_VLAN_CFG_AWARE_ENA			BIT(19)
+#define		ANA_CL_PORT_VLAN_CFG_POP_CNT(x)			((x) << 17)
+
+#define ANA_L2_COMMON_FWD_CFG			0x8a2a8
+#define		ANA_L2_COMMON_FWD_CFG_CPU_DMAC_COPY_ENA	BIT(6)
+
+#define ASM_CFG_STAT_CFG			0x3508
+#define ASM_CFG_PORT(x)				(0x36c4 + 0x4 * (x))
+#define		ASM_CFG_PORT_NO_PREAMBLE_ENA		BIT(8)
+#define		ASM_CFG_PORT_INJ_FORMAT_CFG(x)		((x) << 1)
+#define ASM_RAM_CTRL_RAM_INIT			0x39b8
+
+#define DEV_DEV_CFG_DEV_RST_CTRL		0x0
+#define		DEV_DEV_CFG_DEV_RST_CTRL_SPEED_SEL(x)	((x) << 20)
+#define DEV_MAC_CFG_MAC_ENA		0x1c
+#define		DEV_MAC_CFG_MAC_ENA_RX_ENA		BIT(4)
+#define		DEV_MAC_CFG_MAC_ENA_TX_ENA		BIT(0)
+#define	DEV_MAC_CFG_MAC_IFG		0x34
+#define		DEV_MAC_CFG_MAC_IFG_TX_IFG(x)		((x) << 8)
+#define		DEV_MAC_CFG_MAC_IFG_RX_IFG2(x)		((x) << 4)
+#define		DEV_MAC_CFG_MAC_IFG_RX_IFG1(x)		(x)
+#define	DEV_PCS1G_CFG_PCS1G_CFG		0x40
+#define		DEV_PCS1G_CFG_PCS1G_CFG_PCS_ENA		BIT(0)
+#define	DEV_PCS1G_CFG_PCS1G_MODE	0x44
+#define	DEV_PCS1G_CFG_PCS1G_SD		0x48
+#define	DEV_PCS1G_CFG_PCS1G_ANEG	0x4c
+#define		DEV_PCS1G_CFG_PCS1G_ANEG_ADV_ABILITY(x)	((x) << 16)
+
+#define DSM_RAM_CTRL_RAM_INIT		0x8
+
+#define HSIO_ANA_SERDES1G_DES_CFG		0xac
+#define		HSIO_ANA_SERDES1G_DES_CFG_BW_HYST(x)		((x) << 1)
+#define		HSIO_ANA_SERDES1G_DES_CFG_BW_ANA(x)		((x) << 5)
+#define		HSIO_ANA_SERDES1G_DES_CFG_MBTR_CTRL(x)		((x) << 8)
+#define		HSIO_ANA_SERDES1G_DES_CFG_PHS_CTRL(x)		((x) << 13)
+#define HSIO_ANA_SERDES1G_IB_CFG		0xb0
+#define		HSIO_ANA_SERDES1G_IB_CFG_RESISTOR_CTRL(x)	(x)
+#define		HSIO_ANA_SERDES1G_IB_CFG_EQ_GAIN(x)		((x) << 6)
+#define		HSIO_ANA_SERDES1G_IB_CFG_ENA_OFFSET_COMP	BIT(9)
+#define		HSIO_ANA_SERDES1G_IB_CFG_ENA_DETLEV		BIT(11)
+#define		HSIO_ANA_SERDES1G_IB_CFG_ENA_CMV_TERM		BIT(13)
+#define		HSIO_ANA_SERDES1G_IB_CFG_DET_LEV(x)		((x) << 19)
+#define		HSIO_ANA_SERDES1G_IB_CFG_ACJTAG_HYST(x)		((x) << 24)
+#define HSIO_ANA_SERDES1G_OB_CFG		0xb4
+#define		HSIO_ANA_SERDES1G_OB_CFG_RESISTOR_CTRL(x)	(x)
+#define		HSIO_ANA_SERDES1G_OB_CFG_VCM_CTRL(x)		((x) << 4)
+#define		HSIO_ANA_SERDES1G_OB_CFG_CMM_BIAS_CTRL(x)	((x) << 10)
+#define		HSIO_ANA_SERDES1G_OB_CFG_AMP_CTRL(x)		((x) << 13)
+#define		HSIO_ANA_SERDES1G_OB_CFG_SLP(x)			((x) << 17)
+#define HSIO_ANA_SERDES1G_SER_CFG		0xb8
+#define HSIO_ANA_SERDES1G_COMMON_CFG		0xbc
+#define		HSIO_ANA_SERDES1G_COMMON_CFG_IF_MODE		BIT(0)
+#define		HSIO_ANA_SERDES1G_COMMON_CFG_ENA_LANE		BIT(18)
+#define		HSIO_ANA_SERDES1G_COMMON_CFG_SYS_RST		BIT(31)
+#define HSIO_ANA_SERDES1G_PLL_CFG		0xc0
+#define		HSIO_ANA_SERDES1G_PLL_CFG_FSM_ENA		BIT(7)
+#define		HSIO_ANA_SERDES1G_PLL_CFG_FSM_CTRL_DATA(x)	((x) << 8)
+#define		HSIO_ANA_SERDES1G_PLL_CFG_ENA_RC_DIV2		BIT(21)
+#define HSIO_DIG_SERDES1G_DFT_CFG0		0xc8
+#define HSIO_DIG_SERDES1G_TP_CFG		0xd4
+#define HSIO_DIG_SERDES1G_MISC_CFG		0xdc
+#define		HSIO_DIG_SERDES1G_MISC_CFG_LANE_RST		BIT(0)
+#define HSIO_MCB_SERDES1G_CFG			0xe8
+#define		HSIO_MCB_SERDES1G_CFG_WR_ONE_SHOT		BIT(31)
+#define		HSIO_MCB_SERDES1G_CFG_ADDR(x)			(x)
+
+#define HSIO_ANA_SERDES6G_DES_CFG		0x11c
+#define		HSIO_ANA_SERDES6G_DES_CFG_SWAP_ANA		BIT(0)
+#define		HSIO_ANA_SERDES6G_DES_CFG_BW_ANA(x)		((x) << 1)
+#define		HSIO_ANA_SERDES6G_DES_CFG_SWAP_HYST		BIT(4)
+#define		HSIO_ANA_SERDES6G_DES_CFG_BW_HYST(x)		((x) << 5)
+#define		HSIO_ANA_SERDES6G_DES_CFG_CPMD_SEL(x)		((x) << 8)
+#define		HSIO_ANA_SERDES6G_DES_CFG_MBTR_CTRL(x)		((x) << 10)
+#define		HSIO_ANA_SERDES6G_DES_CFG_PHS_CTRL(x)		((x) << 13)
+#define HSIO_ANA_SERDES6G_IB_CFG		0x120
+#define		HSIO_ANA_SERDES6G_IB_CFG_REG_ENA		BIT(0)
+#define		HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA		BIT(1)
+#define		HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA		BIT(2)
+#define		HSIO_ANA_SERDES6G_IB_CFG_CAL_ENA(x)		((x) << 3)
+#define		HSIO_ANA_SERDES6G_IB_CFG_CONCUR			BIT(4)
+#define		HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA		BIT(5)
+#define		HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(x)	((x) << 7)
+#define		HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(x)	((x) << 9)
+#define		HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(x)	((x) << 11)
+#define		HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(x)	((x) << 13)
+#define		HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(x)	((x) << 15)
+#define		HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(x)	((x) << 18)
+#define		HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(x)		((x) << 20)
+#define		HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(x)		((x) << 24)
+#define		HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL		BIT(28)
+#define		HSIO_ANA_SERDES6G_IB_CFG_SOFSI(x)		((x) << 29)
+#define HSIO_ANA_SERDES6G_IB_CFG1		0x124
+#define		HSIO_ANA_SERDES6G_IB_CFG1_FILT_OFFSET		BIT(4)
+#define		HSIO_ANA_SERDES6G_IB_CFG1_FILT_LP		BIT(5)
+#define		HSIO_ANA_SERDES6G_IB_CFG1_FILT_MID		BIT(6)
+#define		HSIO_ANA_SERDES6G_IB_CFG1_FILT_HP		BIT(7)
+#define		HSIO_ANA_SERDES6G_IB_CFG1_SCALY(x)		((x) << 8)
+#define		HSIO_ANA_SERDES6G_IB_CFG1_TSDET(x)		((x) << 12)
+#define		HSIO_ANA_SERDES6G_IB_CFG1_TJTAG(x)		((x) << 17)
+#define HSIO_ANA_SERDES6G_IB_CFG2		0x128
+#define		HSIO_ANA_SERDES6G_IB_CFG2_UREG(x)		(x)
+#define		HSIO_ANA_SERDES6G_IB_CFG2_UMAX(x)		((x) << 3)
+#define		HSIO_ANA_SERDES6G_IB_CFG2_TCALV(x)		((x) << 5)
+#define		HSIO_ANA_SERDES6G_IB_CFG2_OCALS(x)		((x) << 10)
+#define		HSIO_ANA_SERDES6G_IB_CFG2_OINFS(x)		((x) << 16)
+#define		HSIO_ANA_SERDES6G_IB_CFG2_OINFI(x)		((x) << 22)
+#define		HSIO_ANA_SERDES6G_IB_CFG2_TINFV(x)		((x) << 27)
+#define HSIO_ANA_SERDES6G_IB_CFG3		0x12c
+#define		HSIO_ANA_SERDES6G_IB_CFG3_INI_OFFSET(x)		(x)
+#define		HSIO_ANA_SERDES6G_IB_CFG3_INI_LP(x)		((x) << 6)
+#define		HSIO_ANA_SERDES6G_IB_CFG3_INI_MID(x)		((x) << 12)
+#define		HSIO_ANA_SERDES6G_IB_CFG3_INI_HP(x)		((x) << 18)
+#define HSIO_ANA_SERDES6G_IB_CFG4		0x130
+#define		HSIO_ANA_SERDES6G_IB_CFG4_MAX_OFFSET(x)		(x)
+#define		HSIO_ANA_SERDES6G_IB_CFG4_MAX_LP(x)		((x) << 6)
+#define		HSIO_ANA_SERDES6G_IB_CFG4_MAX_MID(x)		((x) << 12)
+#define		HSIO_ANA_SERDES6G_IB_CFG4_MAX_HP(x)		((x) << 18)
+#define HSIO_ANA_SERDES6G_IB_CFG5		0x134
+#define		HSIO_ANA_SERDES6G_IB_CFG4_MIN_OFFSET(x)		(x)
+#define		HSIO_ANA_SERDES6G_IB_CFG4_MIN_LP(x)		((x) << 6)
+#define		HSIO_ANA_SERDES6G_IB_CFG4_MIN_MID(x)		((x) << 12)
+#define		HSIO_ANA_SERDES6G_IB_CFG4_MIN_HP(x)		((x) << 18)
+#define HSIO_ANA_SERDES6G_OB_CFG		0x138
+#define		HSIO_ANA_SERDES6G_OB_CFG_RESISTOR_CTRL(x)	(x)
+#define		HSIO_ANA_SERDES6G_OB_CFG_SR(x)			((x) << 4)
+#define		HSIO_ANA_SERDES6G_OB_CFG_SR_H			BIT(8)
+#define		HSIO_ANA_SERDES6G_OB_CFG_SEL_RCTRL		BIT(9)
+#define		HSIO_ANA_SERDES6G_OB_CFG_R_COR			BIT(10)
+#define		HSIO_ANA_SERDES6G_OB_CFG_POST1(x)		((x) << 11)
+#define		HSIO_ANA_SERDES6G_OB_CFG_R_ADJ_PDR		BIT(16)
+#define		HSIO_ANA_SERDES6G_OB_CFG_R_ADJ_MUX		BIT(17)
+#define		HSIO_ANA_SERDES6G_OB_CFG_PREC(x)		((x) << 18)
+#define		HSIO_ANA_SERDES6G_OB_CFG_POST0(x)		((x) << 23)
+#define		HSIO_ANA_SERDES6G_OB_CFG_POL			BIT(29)
+#define		HSIO_ANA_SERDES6G_OB_CFG_ENA1V_MODE(x)		((x) << 30)
+#define		HSIO_ANA_SERDES6G_OB_CFG_IDLE			BIT(31)
+#define HSIO_ANA_SERDES6G_OB_CFG1		0x13c
+#define		HSIO_ANA_SERDES6G_OB_CFG1_LEV(x)		(x)
+#define		HSIO_ANA_SERDES6G_OB_CFG1_ENA_CAS(x)		((x) << 6)
+#define HSIO_ANA_SERDES6G_SER_CFG		0x140
+#define HSIO_ANA_SERDES6G_COMMON_CFG		0x144
+#define		HSIO_ANA_SERDES6G_COMMON_CFG_IF_MODE(x)		(x)
+#define		HSIO_ANA_SERDES6G_COMMON_CFG_QRATE(x)		(x << 2)
+#define		HSIO_ANA_SERDES6G_COMMON_CFG_ENA_LANE		BIT(14)
+#define		HSIO_ANA_SERDES6G_COMMON_CFG_SYS_RST		BIT(16)
+#define HSIO_ANA_SERDES6G_PLL_CFG		0x148
+#define		HSIO_ANA_SERDES6G_PLL_CFG_ROT_FRQ		BIT(0)
+#define		HSIO_ANA_SERDES6G_PLL_CFG_ROT_DIR		BIT(1)
+#define		HSIO_ANA_SERDES6G_PLL_CFG_RB_DATA_SEL		BIT(2)
+#define		HSIO_ANA_SERDES6G_PLL_CFG_FSM_OOR_RECAL_ENA	BIT(3)
+#define		HSIO_ANA_SERDES6G_PLL_CFG_FSM_FORCE_SET_ENA	BIT(4)
+#define		HSIO_ANA_SERDES6G_PLL_CFG_FSM_ENA		BIT(5)
+#define		HSIO_ANA_SERDES6G_PLL_CFG_FSM_CTRL_DATA(x)	((x) << 6)
+#define		HSIO_ANA_SERDES6G_PLL_CFG_ENA_ROT		BIT(14)
+#define		HSIO_ANA_SERDES6G_PLL_CFG_DIV4			BIT(15)
+#define		HSIO_ANA_SERDES6G_PLL_CFG_ENA_OFFS(x)		((x) << 16)
+#define HSIO_DIG_SERDES6G_MISC_CFG		0x108
+#define		HSIO_DIG_SERDES6G_MISC_CFG_LANE_RST		BIT(0)
+#define HSIO_MCB_SERDES6G_CFG			0x168
+#define		HSIO_MCB_SERDES6G_CFG_WR_ONE_SHOT		BIT(31)
+#define		HSIO_MCB_SERDES6G_CFG_ADDR(x)			(x)
+#define HSIO_HW_CFGSTAT_HW_CFG			0x16c
+
+#define LRN_COMMON_ACCESS_CTRL			0x0
+#define		LRN_COMMON_ACCESS_CTRL_MAC_TABLE_ACCESS_SHOT	BIT(0)
+#define LRN_COMMON_MAC_ACCESS_CFG0		0x4
+#define LRN_COMMON_MAC_ACCESS_CFG1		0x8
+#define LRN_COMMON_MAC_ACCESS_CFG2		0xc
+#define		LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_ADDR(x)	(x)
+#define		LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_TYPE(x)	((x) << 12)
+#define		LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_VLD	BIT(15)
+#define		LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_LOCKED	BIT(16)
+#define		LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_COPY	BIT(23)
+#define		LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_QU(x)	((x) << 24)
+
+#define QFWD_SYSTEM_SWITCH_PORT_MODE(x)		(0x4 * (x))
+#define		QFWD_SYSTEM_SWITCH_PORT_MODE_PORT_ENA		BIT(17)
+
+#define QS_XTR_GRP_CFG(x)		(0x0 + 4 * (x))
+#define QS_INJ_GRP_CFG(x)		(0x24 + (x) * 4)
+
+#define QSYS_SYSTEM_RESET_CFG			0xf0
+#define QSYS_CALCFG_CAL_AUTO(x)			(0x3d4 + 4 * (x))
+#define QSYS_CALCFG_CAL_CTRL			0x3e8
+#define		QSYS_CALCFG_CAL_CTRL_CAL_MODE(x)		((x) << 11)
+#define QSYS_RAM_CTRL_RAM_INIT			0x3ec
+
+#define REW_RAM_CTRL_RAM_INIT			0x53528
+
+#define VOP_RAM_CTRL_RAM_INIT			0x43638
+
+#define XTR_VALID_BYTES(x)	(4 - ((x) & 3))
+#define MAC_VID			0
+#define CPU_PORT		53
+#define IFH_LEN			7
+#define JR2_BUF_CELL_SZ		60
+#define ETH_ALEN		6
+#define PGID_BROADCAST		510
+#define PGID_UNICAST		511
+
+static const char * const regs_names[] = {
+	"port0", "port1", "port2", "port3", "port4", "port5", "port6", "port7",
+	"port8", "port9", "port10", "port11", "port12", "port13", "port14",
+	"port15", "port16", "port17", "port18", "port19", "port20", "port21",
+	"port22", "port23", "port24", "port25", "port26", "port27", "port28",
+	"port29", "port30", "port31", "port32", "port33", "port34", "port35",
+	"port36", "port37", "port38", "port39", "port40", "port41", "port42",
+	"port43", "port44", "port45", "port46", "port47",
+	"ana_ac", "ana_cl", "ana_l2", "asm", "hsio", "lrn",
+	"qfwd", "qs", "qsys", "rew",
+};
+
+#define REGS_NAMES_COUNT ARRAY_SIZE(regs_names) + 1
+#define MAX_PORT 48
+
+enum jr2_ctrl_regs {
+	ANA_AC = MAX_PORT,
+	ANA_CL,
+	ANA_L2,
+	ASM,
+	HSIO,
+	LRN,
+	QFWD,
+	QS,
+	QSYS,
+	REW,
+};
+
+#define JR2_MIIM_BUS_COUNT 3
+
+struct jr2_phy_port_t {
+	size_t phy_addr;
+	struct mii_dev *bus;
+	u8 serdes_index;
+	u8 phy_mode;
+};
+
+struct jr2_private {
+	void __iomem *regs[REGS_NAMES_COUNT];
+	struct mii_dev *bus[JR2_MIIM_BUS_COUNT];
+	struct jr2_phy_port_t ports[MAX_PORT];
+};
+
+struct jr2_miim_dev {
+	void __iomem *regs;
+	phys_addr_t miim_base;
+	unsigned long miim_size;
+	struct mii_dev *bus;
+};
+
+static const unsigned long jr2_regs_qs[] = {
+	[MSCC_QS_XTR_RD] = 0x8,
+	[MSCC_QS_XTR_FLUSH] = 0x18,
+	[MSCC_QS_XTR_DATA_PRESENT] = 0x1c,
+	[MSCC_QS_INJ_WR] = 0x2c,
+	[MSCC_QS_INJ_CTRL] = 0x34,
+};
+
+static struct jr2_miim_dev miim[JR2_MIIM_BUS_COUNT];
+static int miim_count = -1;
+
+static int mscc_miim_wait_ready(struct jr2_miim_dev *miim)
+{
+	unsigned long deadline;
+	u32 val;
+
+	deadline = timer_get_us() + 250000;
+
+	do {
+		val = readl(miim->regs + GCB_MIIM_MII_STATUS);
+	} while (timer_get_us() <= deadline && (val & GCB_MIIM_STAT_BUSY));
+
+	if (val & GCB_MIIM_STAT_BUSY)
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+static int mscc_miim_read(struct mii_dev *bus, int addr, int devad, int reg)
+{
+	struct jr2_miim_dev *miim = (struct jr2_miim_dev *)bus->priv;
+	u32 val;
+	int ret;
+
+	ret = mscc_miim_wait_ready(miim);
+	if (ret)
+		goto out;
+
+	writel(GCB_MIIM_MII_CMD_VLD | GCB_MIIM_MII_CMD_PHYAD(addr) |
+	       GCB_MIIM_MII_CMD_REGAD(reg) | GCB_MIIM_MII_CMD_OPR_READ,
+	       miim->regs + GCB_MIIM_MII_CMD);
+
+	ret = mscc_miim_wait_ready(miim);
+	if (ret)
+		goto out;
+
+	val = readl(miim->regs + GCB_MIIM_DATA);
+	if (val & GCB_MIIM_DATA_ERROR) {
+		ret = -EIO;
+		goto out;
+	}
+
+	ret = val & 0xFFFF;
+ out:
+	return ret;
+}
+
+static int mscc_miim_write(struct mii_dev *bus, int addr, int devad, int reg,
+			   u16 val)
+{
+	struct jr2_miim_dev *miim = (struct jr2_miim_dev *)bus->priv;
+	int ret;
+
+	ret = mscc_miim_wait_ready(miim);
+	if (ret < 0)
+		goto out;
+
+	writel(GCB_MIIM_MII_CMD_VLD | GCB_MIIM_MII_CMD_PHYAD(addr) |
+	       GCB_MIIM_MII_CMD_REGAD(reg) | GCB_MIIM_MII_CMD_WRDATA(val) |
+	       GCB_MIIM_MII_CMD_OPR_WRITE, miim->regs + GCB_MIIM_MII_CMD);
+
+ out:
+	return ret;
+}
+
+static struct mii_dev *jr2_mdiobus_init(phys_addr_t miim_base,
+					unsigned long miim_size)
+{
+	struct mii_dev *bus;
+
+	bus = mdio_alloc();
+	if (!bus)
+		return NULL;
+
+	++miim_count;
+	sprintf(bus->name, "miim-bus%d", miim_count);
+
+	miim[miim_count].regs = ioremap(miim_base, miim_size);
+	miim[miim_count].miim_base = miim_base;
+	miim[miim_count].miim_size = miim_size;
+	bus->priv = &miim[miim_count];
+	bus->read = mscc_miim_read;
+	bus->write = mscc_miim_write;
+
+	if (mdio_register(bus))
+		return NULL;
+
+	miim[miim_count].bus = bus;
+	return bus;
+}
+
+static void jr2_cpu_capture_setup(struct jr2_private *priv)
+{
+	/* ASM: No preamble and IFH prefix on CPU injected frames */
+	writel(ASM_CFG_PORT_NO_PREAMBLE_ENA |
+	       ASM_CFG_PORT_INJ_FORMAT_CFG(1),
+	       priv->regs[ASM] + ASM_CFG_PORT(CPU_PORT));
+
+	/* Set Manual injection via DEVCPU_QS registers for CPU queue 0 */
+	writel(0x5, priv->regs[QS] + QS_INJ_GRP_CFG(0));
+
+	/* Set Manual extraction via DEVCPU_QS registers for CPU queue 0 */
+	writel(0x7, priv->regs[QS] + QS_XTR_GRP_CFG(0));
+
+	/* Enable CPU port for any frame transfer */
+	setbits_le32(priv->regs[QFWD] + QFWD_SYSTEM_SWITCH_PORT_MODE(CPU_PORT),
+		     QFWD_SYSTEM_SWITCH_PORT_MODE_PORT_ENA);
+
+	/* Send a copy to CPU when found as forwarding entry */
+	setbits_le32(priv->regs[ANA_L2] + ANA_L2_COMMON_FWD_CFG,
+		     ANA_L2_COMMON_FWD_CFG_CPU_DMAC_COPY_ENA);
+}
+
+static void jr2_port_init(struct jr2_private *priv, int port)
+{
+	void __iomem *regs = priv->regs[port];
+
+	/* Enable PCS */
+	writel(DEV_PCS1G_CFG_PCS1G_CFG_PCS_ENA,
+	       regs + DEV_PCS1G_CFG_PCS1G_CFG);
+
+	/* Disable Signal Detect */
+	writel(0, regs + DEV_PCS1G_CFG_PCS1G_SD);
+
+	/* Enable MAC RX and TX */
+	writel(DEV_MAC_CFG_MAC_ENA_RX_ENA |
+	       DEV_MAC_CFG_MAC_ENA_TX_ENA,
+	       regs + DEV_MAC_CFG_MAC_ENA);
+
+	/* Clear sgmii_mode_ena */
+	writel(0, regs + DEV_PCS1G_CFG_PCS1G_MODE);
+
+	/*
+	 * Clear sw_resolve_ena(bit 0) and set adv_ability to
+	 * something meaningful just in case
+	 */
+	writel(DEV_PCS1G_CFG_PCS1G_ANEG_ADV_ABILITY(0x20),
+	       regs + DEV_PCS1G_CFG_PCS1G_ANEG);
+
+	/* Set MAC IFG Gaps */
+	writel(DEV_MAC_CFG_MAC_IFG_TX_IFG(4) |
+	       DEV_MAC_CFG_MAC_IFG_RX_IFG1(5) |
+	       DEV_MAC_CFG_MAC_IFG_RX_IFG2(1),
+	       regs + DEV_MAC_CFG_MAC_IFG);
+
+	/* Set link speed and release all resets */
+	writel(DEV_DEV_CFG_DEV_RST_CTRL_SPEED_SEL(2),
+	       regs + DEV_DEV_CFG_DEV_RST_CTRL);
+
+	/* Make VLAN aware for CPU traffic */
+	writel(ANA_CL_PORT_VLAN_CFG_AWARE_ENA |
+	       ANA_CL_PORT_VLAN_CFG_POP_CNT(1) |
+	       MAC_VID,
+	       priv->regs[ANA_CL] + ANA_CL_PORT_VLAN_CFG(port));
+
+	/* Enable CPU port for any frame transfer */
+	setbits_le32(priv->regs[QFWD] + QFWD_SYSTEM_SWITCH_PORT_MODE(port),
+		     QFWD_SYSTEM_SWITCH_PORT_MODE_PORT_ENA);
+}
+
+static void serdes6g_write(void __iomem *base, u32 addr)
+{
+	u32 data;
+
+	writel(HSIO_MCB_SERDES6G_CFG_WR_ONE_SHOT |
+	       HSIO_MCB_SERDES6G_CFG_ADDR(addr),
+	       base + HSIO_MCB_SERDES6G_CFG);
+
+	do {
+		data = readl(base + HSIO_MCB_SERDES6G_CFG);
+	} while (data & HSIO_MCB_SERDES6G_CFG_WR_ONE_SHOT);
+}
+
+static void serdes6g_setup(void __iomem *base, uint32_t addr,
+			   phy_interface_t interface)
+{
+	u32 ib_if_mode = 0;
+	u32 ib_qrate = 0;
+	u32 ib_cal_ena = 0;
+	u32 ib1_tsdet = 0;
+	u32 ob_lev = 0;
+	u32 ob_ena_cas = 0;
+	u32 ob_ena1v_mode = 0;
+	u32 des_bw_ana = 0;
+	u32 pll_fsm_ctrl_data = 0;
+
+	switch (interface) {
+	case PHY_INTERFACE_MODE_SGMII:
+		ib_if_mode = 1;
+		ib_qrate = 1;
+		ib_cal_ena = 1;
+		ib1_tsdet = 3;
+		ob_lev = 48;
+		ob_ena_cas = 2;
+		ob_ena1v_mode = 1;
+		des_bw_ana = 3;
+		pll_fsm_ctrl_data = 60;
+		break;
+	case PHY_INTERFACE_MODE_QSGMII:
+		ib_if_mode = 3;
+		ib1_tsdet = 16;
+		ob_lev = 24;
+		des_bw_ana = 5;
+		pll_fsm_ctrl_data = 120;
+		break;
+	default:
+		pr_err("Interface not supported\n");
+		return;
+	}
+
+	if (interface == PHY_INTERFACE_MODE_QSGMII)
+		writel(0xfff, base + HSIO_HW_CFGSTAT_HW_CFG);
+
+	writel(HSIO_ANA_SERDES6G_COMMON_CFG_IF_MODE(3),
+	       base + HSIO_ANA_SERDES6G_COMMON_CFG);
+	writel(HSIO_ANA_SERDES6G_PLL_CFG_FSM_CTRL_DATA(120) |
+	       HSIO_ANA_SERDES6G_PLL_CFG_ENA_OFFS(3),
+	       base + HSIO_ANA_SERDES6G_PLL_CFG);
+	writel(HSIO_ANA_SERDES6G_IB_CFG_REG_ENA |
+	       HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA |
+	       HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA |
+	       HSIO_ANA_SERDES6G_IB_CFG_CONCUR |
+	       HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA |
+	       HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(0) |
+	       HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(2) |
+	       HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(1) |
+	       HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(1) |
+	       HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(7) |
+	       HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(1) |
+	       HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(5) |
+	       HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(13) |
+	       HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL |
+	       HSIO_ANA_SERDES6G_IB_CFG_SOFSI(1),
+	       base + HSIO_ANA_SERDES6G_IB_CFG);
+	writel(HSIO_ANA_SERDES6G_IB_CFG1_FILT_OFFSET |
+	       HSIO_ANA_SERDES6G_IB_CFG1_FILT_LP |
+	       HSIO_ANA_SERDES6G_IB_CFG1_FILT_MID |
+	       HSIO_ANA_SERDES6G_IB_CFG1_FILT_HP |
+	       HSIO_ANA_SERDES6G_IB_CFG1_SCALY(15) |
+	       HSIO_ANA_SERDES6G_IB_CFG1_TSDET(3) |
+	       HSIO_ANA_SERDES6G_IB_CFG1_TJTAG(8),
+	       base + HSIO_ANA_SERDES6G_IB_CFG1);
+	writel(HSIO_DIG_SERDES6G_MISC_CFG_LANE_RST,
+	       base + HSIO_DIG_SERDES6G_MISC_CFG);
+
+	serdes6g_write(base, addr);
+
+	writel(HSIO_ANA_SERDES6G_IB_CFG_REG_ENA |
+	       HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA |
+	       HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA |
+	       HSIO_ANA_SERDES6G_IB_CFG_CONCUR |
+	       HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA |
+	       HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(0) |
+	       HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(2) |
+	       HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(1) |
+	       HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(1) |
+	       HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(0) |
+	       HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(1) |
+	       HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(5) |
+	       HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(13) |
+	       HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL |
+	       HSIO_ANA_SERDES6G_IB_CFG_SOFSI(1),
+	       base + HSIO_ANA_SERDES6G_IB_CFG);
+	writel(HSIO_ANA_SERDES6G_IB_CFG1_FILT_OFFSET |
+	       HSIO_ANA_SERDES6G_IB_CFG1_FILT_LP |
+	       HSIO_ANA_SERDES6G_IB_CFG1_FILT_MID |
+	       HSIO_ANA_SERDES6G_IB_CFG1_FILT_HP |
+	       HSIO_ANA_SERDES6G_IB_CFG1_SCALY(15) |
+	       HSIO_ANA_SERDES6G_IB_CFG1_TSDET(16) |
+	       HSIO_ANA_SERDES6G_IB_CFG1_TJTAG(8),
+	       base + HSIO_ANA_SERDES6G_IB_CFG1);
+
+	writel(0x0, base + HSIO_ANA_SERDES6G_SER_CFG);
+	writel(HSIO_ANA_SERDES6G_COMMON_CFG_IF_MODE(ib_if_mode) |
+	       HSIO_ANA_SERDES6G_COMMON_CFG_QRATE(ib_qrate) |
+	       HSIO_ANA_SERDES6G_COMMON_CFG_ENA_LANE |
+	       HSIO_ANA_SERDES6G_COMMON_CFG_SYS_RST,
+	       base + HSIO_ANA_SERDES6G_COMMON_CFG);
+	writel(HSIO_DIG_SERDES6G_MISC_CFG_LANE_RST,
+	       base + HSIO_DIG_SERDES6G_MISC_CFG);
+
+	writel(HSIO_ANA_SERDES6G_OB_CFG_RESISTOR_CTRL(1) |
+	       HSIO_ANA_SERDES6G_OB_CFG_SR(7) |
+	       HSIO_ANA_SERDES6G_OB_CFG_SR_H |
+	       HSIO_ANA_SERDES6G_OB_CFG_ENA1V_MODE(ob_ena1v_mode) |
+	       HSIO_ANA_SERDES6G_OB_CFG_POL, base + HSIO_ANA_SERDES6G_OB_CFG);
+	writel(HSIO_ANA_SERDES6G_OB_CFG1_LEV(ob_lev) |
+	       HSIO_ANA_SERDES6G_OB_CFG1_ENA_CAS(ob_ena_cas),
+	       base + HSIO_ANA_SERDES6G_OB_CFG1);
+
+	writel(HSIO_ANA_SERDES6G_DES_CFG_BW_ANA(des_bw_ana) |
+	       HSIO_ANA_SERDES6G_DES_CFG_BW_HYST(5) |
+	       HSIO_ANA_SERDES6G_DES_CFG_MBTR_CTRL(2) |
+	       HSIO_ANA_SERDES6G_DES_CFG_PHS_CTRL(6),
+	       base + HSIO_ANA_SERDES6G_DES_CFG);
+	writel(HSIO_ANA_SERDES6G_PLL_CFG_FSM_CTRL_DATA(pll_fsm_ctrl_data) |
+	       HSIO_ANA_SERDES6G_PLL_CFG_ENA_OFFS(3),
+	       base + HSIO_ANA_SERDES6G_PLL_CFG);
+
+	serdes6g_write(base, addr);
+
+	/* set pll_fsm_ena = 1 */
+	writel(HSIO_ANA_SERDES6G_PLL_CFG_FSM_ENA |
+	       HSIO_ANA_SERDES6G_PLL_CFG_FSM_CTRL_DATA(pll_fsm_ctrl_data) |
+	       HSIO_ANA_SERDES6G_PLL_CFG_ENA_OFFS(3),
+	       base + HSIO_ANA_SERDES6G_PLL_CFG);
+
+	serdes6g_write(base, addr);
+
+	/* wait 20ms for pll bringup */
+	mdelay(20);
+
+	/* start IB calibration by setting ib_cal_ena and clearing lane_rst */
+	writel(HSIO_ANA_SERDES6G_IB_CFG_REG_ENA |
+	       HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA |
+	       HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA |
+	       HSIO_ANA_SERDES6G_IB_CFG_CAL_ENA(ib_cal_ena) |
+	       HSIO_ANA_SERDES6G_IB_CFG_CONCUR |
+	       HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA |
+	       HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(0) |
+	       HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(2) |
+	       HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(1) |
+	       HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(1) |
+	       HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(0) |
+	       HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(1) |
+	       HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(5) |
+	       HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(13) |
+	       HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL |
+	       HSIO_ANA_SERDES6G_IB_CFG_SOFSI(1),
+	       base + HSIO_ANA_SERDES6G_IB_CFG);
+	writel(0x0, base + HSIO_DIG_SERDES6G_MISC_CFG);
+
+	serdes6g_write(base, addr);
+
+	/* wait 60 for calibration */
+	mdelay(60);
+
+	/* set ib_tsdet and ib_reg_pat_sel_offset back to correct values */
+	writel(HSIO_ANA_SERDES6G_IB_CFG_REG_ENA |
+	       HSIO_ANA_SERDES6G_IB_CFG_EQZ_ENA |
+	       HSIO_ANA_SERDES6G_IB_CFG_SAM_ENA |
+	       HSIO_ANA_SERDES6G_IB_CFG_CAL_ENA(ib_cal_ena) |
+	       HSIO_ANA_SERDES6G_IB_CFG_CONCUR |
+	       HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_ENA |
+	       HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_OFF(0) |
+	       HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_LP(2) |
+	       HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_MID(1) |
+	       HSIO_ANA_SERDES6G_IB_CFG_REG_PAT_SEL_HP(1) |
+	       HSIO_ANA_SERDES6G_IB_CFG_SIG_DET_CLK_SEL(7) |
+	       HSIO_ANA_SERDES6G_IB_CFG_TERM_MODE_SEL(1) |
+	       HSIO_ANA_SERDES6G_IB_CFG_ICML_ADJ(5) |
+	       HSIO_ANA_SERDES6G_IB_CFG_RTRM_ADJ(13) |
+	       HSIO_ANA_SERDES6G_IB_CFG_VBULK_SEL |
+	       HSIO_ANA_SERDES6G_IB_CFG_SOFSI(1),
+	       base + HSIO_ANA_SERDES6G_IB_CFG);
+	writel(HSIO_ANA_SERDES6G_IB_CFG1_FILT_OFFSET |
+	       HSIO_ANA_SERDES6G_IB_CFG1_FILT_LP |
+	       HSIO_ANA_SERDES6G_IB_CFG1_FILT_MID |
+	       HSIO_ANA_SERDES6G_IB_CFG1_FILT_HP |
+	       HSIO_ANA_SERDES6G_IB_CFG1_SCALY(15) |
+	       HSIO_ANA_SERDES6G_IB_CFG1_TSDET(ib1_tsdet) |
+	       HSIO_ANA_SERDES6G_IB_CFG1_TJTAG(8),
+	       base + HSIO_ANA_SERDES6G_IB_CFG1);
+
+	serdes6g_write(base, addr);
+}
+
+static void serdes1g_write(void __iomem *base, u32 addr)
+{
+	u32 data;
+
+	writel(HSIO_MCB_SERDES1G_CFG_WR_ONE_SHOT |
+	       HSIO_MCB_SERDES1G_CFG_ADDR(addr),
+	       base + HSIO_MCB_SERDES1G_CFG);
+
+	do {
+		data = readl(base + HSIO_MCB_SERDES1G_CFG);
+	} while (data & HSIO_MCB_SERDES1G_CFG_WR_ONE_SHOT);
+}
+
+static void serdes1g_setup(void __iomem *base, uint32_t addr,
+			   phy_interface_t interface)
+{
+	writel(0x0, base + HSIO_ANA_SERDES1G_SER_CFG);
+	writel(0x0, base + HSIO_DIG_SERDES1G_TP_CFG);
+	writel(0x0, base + HSIO_DIG_SERDES1G_DFT_CFG0);
+	writel(HSIO_ANA_SERDES1G_OB_CFG_RESISTOR_CTRL(1) |
+	       HSIO_ANA_SERDES1G_OB_CFG_VCM_CTRL(4) |
+	       HSIO_ANA_SERDES1G_OB_CFG_CMM_BIAS_CTRL(2) |
+	       HSIO_ANA_SERDES1G_OB_CFG_AMP_CTRL(12) |
+	       HSIO_ANA_SERDES1G_OB_CFG_SLP(3),
+	       base + HSIO_ANA_SERDES1G_OB_CFG);
+	writel(HSIO_ANA_SERDES1G_IB_CFG_RESISTOR_CTRL(13) |
+	       HSIO_ANA_SERDES1G_IB_CFG_EQ_GAIN(2) |
+	       HSIO_ANA_SERDES1G_IB_CFG_ENA_OFFSET_COMP |
+	       HSIO_ANA_SERDES1G_IB_CFG_ENA_DETLEV |
+	       HSIO_ANA_SERDES1G_IB_CFG_ENA_CMV_TERM |
+	       HSIO_ANA_SERDES1G_IB_CFG_DET_LEV(3) |
+	       HSIO_ANA_SERDES1G_IB_CFG_ACJTAG_HYST(1),
+	       base + HSIO_ANA_SERDES1G_IB_CFG);
+	writel(HSIO_ANA_SERDES1G_DES_CFG_BW_HYST(7) |
+	       HSIO_ANA_SERDES1G_DES_CFG_BW_ANA(6) |
+	       HSIO_ANA_SERDES1G_DES_CFG_MBTR_CTRL(2) |
+	       HSIO_ANA_SERDES1G_DES_CFG_PHS_CTRL(6),
+	       base + HSIO_ANA_SERDES1G_DES_CFG);
+	writel(HSIO_DIG_SERDES1G_MISC_CFG_LANE_RST,
+	       base + HSIO_DIG_SERDES1G_MISC_CFG);
+	writel(HSIO_ANA_SERDES1G_PLL_CFG_FSM_ENA |
+	       HSIO_ANA_SERDES1G_PLL_CFG_FSM_CTRL_DATA(0xc8) |
+	       HSIO_ANA_SERDES1G_PLL_CFG_ENA_RC_DIV2,
+	       base + HSIO_ANA_SERDES1G_PLL_CFG);
+	writel(HSIO_ANA_SERDES1G_COMMON_CFG_IF_MODE |
+	       HSIO_ANA_SERDES1G_COMMON_CFG_ENA_LANE |
+	       HSIO_ANA_SERDES1G_COMMON_CFG_SYS_RST,
+	       base + HSIO_ANA_SERDES1G_COMMON_CFG);
+
+	serdes1g_write(base, addr);
+
+	setbits_le32(base + HSIO_ANA_SERDES1G_COMMON_CFG,
+		     HSIO_ANA_SERDES1G_COMMON_CFG_SYS_RST);
+
+	serdes1g_write(base, addr);
+
+	clrbits_le32(base + HSIO_DIG_SERDES1G_MISC_CFG,
+		     HSIO_DIG_SERDES1G_MISC_CFG_LANE_RST);
+
+	serdes1g_write(base, addr);
+}
+
+static int ram_init(u32 val, void __iomem *addr)
+{
+	writel(val, addr);
+
+	if (wait_for_bit_le32(addr, BIT(1), false, 2000, false)) {
+		printf("Timeout in memory reset, reg = 0x%08x\n", val);
+		return 1;
+	}
+
+	return 0;
+}
+
+static int jr2_switch_init(struct jr2_private *priv)
+{
+	/* Initialize memories */
+	ram_init(0x3, priv->regs[QSYS] + QSYS_RAM_CTRL_RAM_INIT);
+	ram_init(0x3, priv->regs[ASM] + ASM_RAM_CTRL_RAM_INIT);
+	ram_init(0x3, priv->regs[ANA_AC] + ANA_AC_RAM_CTRL_RAM_INIT);
+	ram_init(0x3, priv->regs[REW] + REW_RAM_CTRL_RAM_INIT);
+
+	/* Reset counters */
+	writel(0x1, priv->regs[ANA_AC] + ANA_AC_STAT_GLOBAL_CFG_PORT_RESET);
+	writel(0x1, priv->regs[ASM] + ASM_CFG_STAT_CFG);
+
+	/* Enable switch-core and queue system */
+	writel(0x1, priv->regs[QSYS] + QSYS_SYSTEM_RESET_CFG);
+
+	return 0;
+}
+
+static void jr2_switch_config(struct jr2_private *priv)
+{
+	writel(0x55555555, priv->regs[QSYS] + QSYS_CALCFG_CAL_AUTO(0));
+	writel(0x55555555, priv->regs[QSYS] + QSYS_CALCFG_CAL_AUTO(1));
+	writel(0x55555555, priv->regs[QSYS] + QSYS_CALCFG_CAL_AUTO(2));
+	writel(0x55555555, priv->regs[QSYS] + QSYS_CALCFG_CAL_AUTO(3));
+
+	writel(readl(priv->regs[QSYS] + QSYS_CALCFG_CAL_CTRL) |
+	       QSYS_CALCFG_CAL_CTRL_CAL_MODE(8),
+	       priv->regs[QSYS] + QSYS_CALCFG_CAL_CTRL);
+}
+
+static int jr2_initialize(struct jr2_private *priv)
+{
+	int ret, i;
+
+	/* Initialize switch memories, enable core */
+	ret = jr2_switch_init(priv);
+	if (ret)
+		return ret;
+
+	jr2_switch_config(priv);
+
+	for (i = 0; i < MAX_PORT; i++)
+		jr2_port_init(priv, i);
+
+	jr2_cpu_capture_setup(priv);
+
+	return 0;
+}
+
+static inline int jr2_vlant_wait_for_completion(struct jr2_private *priv)
+{
+	if (wait_for_bit_le32(priv->regs[LRN] + LRN_COMMON_ACCESS_CTRL,
+			      LRN_COMMON_ACCESS_CTRL_MAC_TABLE_ACCESS_SHOT,
+			      false, 2000, false))
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+static int jr2_mac_table_add(struct jr2_private *priv,
+			     const unsigned char mac[ETH_ALEN], int pgid)
+{
+	u32 macl = 0, mach = 0;
+
+	/*
+	 * Set the MAC address to handle and the vlan associated in a format
+	 * understood by the hardware.
+	 */
+	mach |= MAC_VID << 16;
+	mach |= ((u32)mac[0]) << 8;
+	mach |= ((u32)mac[1]) << 0;
+	macl |= ((u32)mac[2]) << 24;
+	macl |= ((u32)mac[3]) << 16;
+	macl |= ((u32)mac[4]) << 8;
+	macl |= ((u32)mac[5]) << 0;
+
+	writel(mach, priv->regs[LRN] + LRN_COMMON_MAC_ACCESS_CFG0);
+	writel(macl, priv->regs[LRN] + LRN_COMMON_MAC_ACCESS_CFG1);
+
+	writel(LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_ADDR(pgid) |
+	       LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_TYPE(0x3) |
+	       LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_COPY |
+	       LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_QU(0) |
+	       LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_VLD |
+	       LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_LOCKED,
+	       priv->regs[LRN] + LRN_COMMON_MAC_ACCESS_CFG2);
+
+	writel(LRN_COMMON_ACCESS_CTRL_MAC_TABLE_ACCESS_SHOT,
+	       priv->regs[LRN] + LRN_COMMON_ACCESS_CTRL);
+
+	return jr2_vlant_wait_for_completion(priv);
+}
+
+static int jr2_write_hwaddr(struct udevice *dev)
+{
+	struct jr2_private *priv = dev_get_priv(dev);
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+
+	return jr2_mac_table_add(priv, pdata->enetaddr, PGID_UNICAST);
+}
+
+static void serdes_setup(struct jr2_private *priv)
+{
+	size_t mask;
+	int i = 0;
+
+	for (i = 0; i < MAX_PORT; ++i) {
+		if (!priv->ports[i].bus || priv->ports[i].serdes_index == 0xff)
+			continue;
+
+		mask = BIT(priv->ports[i].serdes_index);
+		if (priv->ports[i].serdes_index < SERDES1G_MAX) {
+			serdes1g_setup(priv->regs[HSIO], mask,
+				       priv->ports[i].phy_mode);
+		} else {
+			mask >>= SERDES6G(0);
+			serdes6g_setup(priv->regs[HSIO], mask,
+				       priv->ports[i].phy_mode);
+		}
+	}
+}
+
+static int jr2_start(struct udevice *dev)
+{
+	struct jr2_private *priv = dev_get_priv(dev);
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	const unsigned char mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff };
+	int ret;
+
+	ret = jr2_initialize(priv);
+	if (ret)
+		return ret;
+
+	/* Set MAC address tables entries for CPU redirection */
+	ret = jr2_mac_table_add(priv, mac, PGID_BROADCAST);
+	if (ret)
+		return ret;
+
+	ret = jr2_mac_table_add(priv, pdata->enetaddr, PGID_UNICAST);
+	if (ret)
+		return ret;
+
+	serdes_setup(priv);
+
+	return 0;
+}
+
+static void jr2_stop(struct udevice *dev)
+{
+}
+
+static int jr2_send(struct udevice *dev, void *packet, int length)
+{
+	struct jr2_private *priv = dev_get_priv(dev);
+	u32 ifh[IFH_LEN];
+	u32 *buf = packet;
+
+	memset(ifh, '\0', IFH_LEN);
+
+	/* Set DST PORT_MASK */
+	ifh[0] = htonl(0);
+	ifh[1] = htonl(0x1FFFFF);
+	ifh[2] = htonl(~0);
+	/* Set DST_MODE to INJECT and UPDATE_FCS */
+	ifh[5] = htonl(0x4c0);
+
+	return mscc_send(priv->regs[QS], jr2_regs_qs,
+			 ifh, IFH_LEN, buf, length);
+}
+
+static int jr2_recv(struct udevice *dev, int flags, uchar **packetp)
+{
+	struct jr2_private *priv = dev_get_priv(dev);
+	u32 *rxbuf = (u32 *)net_rx_packets[0];
+	int byte_cnt = 0;
+
+	byte_cnt = mscc_recv(priv->regs[QS], jr2_regs_qs, rxbuf, IFH_LEN,
+			     false);
+
+	*packetp = net_rx_packets[0];
+
+	return byte_cnt;
+}
+
+static struct mii_dev *get_mdiobus(phys_addr_t base, unsigned long size)
+{
+	int i = 0;
+
+	for (i = 0; i < JR2_MIIM_BUS_COUNT; ++i)
+		if (miim[i].miim_base == base && miim[i].miim_size == size)
+			return miim[i].bus;
+
+	return NULL;
+}
+
+static void add_port_entry(struct jr2_private *priv, size_t index,
+			   size_t phy_addr, struct mii_dev *bus,
+			   u8 serdes_index, u8 phy_mode)
+{
+	priv->ports[index].phy_addr = phy_addr;
+	priv->ports[index].bus = bus;
+	priv->ports[index].serdes_index = serdes_index;
+	priv->ports[index].phy_mode = phy_mode;
+}
+
+static int jr2_probe(struct udevice *dev)
+{
+	struct jr2_private *priv = dev_get_priv(dev);
+	int i;
+	int ret;
+	struct resource res;
+	fdt32_t faddr;
+	phys_addr_t addr_base;
+	unsigned long addr_size;
+	ofnode eth_node, node, mdio_node;
+	size_t phy_addr;
+	struct mii_dev *bus;
+	struct ofnode_phandle_args phandle;
+	struct phy_device *phy;
+
+	if (!priv)
+		return -EINVAL;
+
+	/* Get registers and map them to the private structure */
+	for (i = 0; i < ARRAY_SIZE(regs_names); i++) {
+		priv->regs[i] = dev_remap_addr_name(dev, regs_names[i]);
+		if (!priv->regs[i]) {
+			debug
+			    ("Error can't get regs base addresses for %s\n",
+			     regs_names[i]);
+			return -ENOMEM;
+		}
+	}
+
+	/* Initialize miim buses */
+	memset(&miim, 0x0, sizeof(struct jr2_miim_dev) * JR2_MIIM_BUS_COUNT);
+
+	/* iterate all the ports and find out on which bus they are */
+	i = 0;
+	eth_node = dev_read_first_subnode(dev);
+	for (node = ofnode_first_subnode(eth_node);
+	     ofnode_valid(node);
+	     node = ofnode_next_subnode(node)) {
+		if (ofnode_read_resource(node, 0, &res))
+			return -ENOMEM;
+		i = res.start;
+
+		ret = ofnode_parse_phandle_with_args(node, "phy-handle", NULL,
+						     0, 0, &phandle);
+		if (ret)
+			continue;
+
+		/* Get phy address on mdio bus */
+		if (ofnode_read_resource(phandle.node, 0, &res))
+			return -ENOMEM;
+		phy_addr = res.start;
+
+		/* Get mdio node */
+		mdio_node = ofnode_get_parent(phandle.node);
+
+		if (ofnode_read_resource(mdio_node, 0, &res))
+			return -ENOMEM;
+		faddr = cpu_to_fdt32(res.start);
+
+		addr_base = ofnode_translate_address(mdio_node, &faddr);
+		addr_size = res.end - res.start;
+
+		/* If the bus is new then create a new bus */
+		if (!get_mdiobus(addr_base, addr_size))
+			priv->bus[miim_count] =
+				jr2_mdiobus_init(addr_base, addr_size);
+
+		/* Connect mdio bus with the port */
+		bus = get_mdiobus(addr_base, addr_size);
+
+		/* Get serdes info */
+		ret = ofnode_parse_phandle_with_args(node, "phys", NULL,
+						     3, 0, &phandle);
+		if (ret)
+			return -ENOMEM;
+
+		add_port_entry(priv, i, phy_addr, bus, phandle.args[1],
+			       phandle.args[2]);
+	}
+
+	for (i = 0; i < MAX_PORT; i++) {
+		if (!priv->ports[i].bus)
+			continue;
+
+		phy = phy_connect(priv->ports[i].bus,
+				  priv->ports[i].phy_addr, dev,
+				  PHY_INTERFACE_MODE_NONE);
+		if (phy)
+			board_phy_config(phy);
+	}
+
+	return 0;
+}
+
+static int jr2_remove(struct udevice *dev)
+{
+	struct jr2_private *priv = dev_get_priv(dev);
+	int i;
+
+	for (i = 0; i < JR2_MIIM_BUS_COUNT; i++) {
+		mdio_unregister(priv->bus[i]);
+		mdio_free(priv->bus[i]);
+	}
+
+	return 0;
+}
+
+static const struct eth_ops jr2_ops = {
+	.start        = jr2_start,
+	.stop         = jr2_stop,
+	.send         = jr2_send,
+	.recv         = jr2_recv,
+	.write_hwaddr = jr2_write_hwaddr,
+};
+
+static const struct udevice_id mscc_jr2_ids[] = {
+	{.compatible = "mscc,vsc7454-switch" },
+	{ /* Sentinel */ }
+};
+
+U_BOOT_DRIVER(jr2) = {
+	.name				= "jr2-switch",
+	.id				= UCLASS_ETH,
+	.of_match			= mscc_jr2_ids,
+	.probe				= jr2_probe,
+	.remove				= jr2_remove,
+	.ops				= &jr2_ops,
+	.priv_auto_alloc_size		= sizeof(struct jr2_private),
+	.platdata_auto_alloc_size	= sizeof(struct eth_pdata),
+};
diff --git a/drivers/net/mscc_eswitch/ocelot_switch.c b/drivers/net/mscc_eswitch/ocelot_switch.c
index bf08c35..815c2da 100644
--- a/drivers/net/mscc_eswitch/ocelot_switch.c
+++ b/drivers/net/mscc_eswitch/ocelot_switch.c
@@ -142,18 +142,16 @@
 
 static struct mscc_miim_dev miim[NUM_PHY];
 
-static int mscc_miim_reset(struct mii_dev *bus)
+static void mscc_phy_reset(void)
 {
-	struct mscc_miim_dev *miim = (struct mscc_miim_dev *)bus->priv;
-
-	if (miim->phy_regs) {
-		writel(0, miim->phy_regs + PHY_CFG);
-		writel(PHY_CFG_RST | PHY_CFG_COMMON_RST
-		       | PHY_CFG_ENA, miim->phy_regs + PHY_CFG);
-		mdelay(500);
+	writel(0, miim[INTERNAL].phy_regs + PHY_CFG);
+	writel(PHY_CFG_RST | PHY_CFG_COMMON_RST
+	       | PHY_CFG_ENA, miim[INTERNAL].phy_regs + PHY_CFG);
+	if (wait_for_bit_le32(miim[INTERNAL].phy_regs + PHY_STAT,
+			      PHY_STAT_SUPERVISOR_COMPLETE,
+			      true, 2000, false)) {
+		pr_err("Timeout in phy reset\n");
 	}
-
-	return 0;
 }
 
 /* For now only setup the internal mdio bus */
@@ -194,7 +192,6 @@
 	miim[INTERNAL].phy_regs = ioremap(phy_base[PHY], phy_size[PHY]);
 	miim[INTERNAL].regs = ioremap(phy_base[MIIM], phy_size[MIIM]);
 	bus->priv = &miim[INTERNAL];
-	bus->reset = mscc_miim_reset;
 	bus->read = mscc_miim_read;
 	bus->write = mscc_miim_write;
 
@@ -210,13 +207,8 @@
 
 static void ocelot_stop(struct udevice *dev)
 {
-	struct ocelot_private *priv = dev_get_priv(dev);
-	int i;
-
 	mscc_switch_reset();
-	for (i = 0; i < NUM_PHY; i++)
-		if (priv->bus[i])
-			mscc_miim_reset(priv->bus[i]);
+	mscc_phy_reset();
 }
 
 static void ocelot_cpu_capture_setup(struct ocelot_private *priv)
@@ -473,6 +465,7 @@
 	}
 
 	priv->bus[INTERNAL] = ocelot_mdiobus_init(dev);
+	mscc_phy_reset();
 
 	for (i = 0; i < 4; i++) {
 		phy_connect(priv->bus[INTERNAL], i, dev,
diff --git a/drivers/net/mscc_eswitch/servalt_switch.c b/drivers/net/mscc_eswitch/servalt_switch.c
new file mode 100644
index 0000000..995c623
--- /dev/null
+++ b/drivers/net/mscc_eswitch/servalt_switch.c
@@ -0,0 +1,622 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2019 Microsemi Corporation
+ */
+
+#include <common.h>
+#include <config.h>
+#include <dm.h>
+#include <dm/of_access.h>
+#include <dm/of_addr.h>
+#include <fdt_support.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <miiphy.h>
+#include <net.h>
+#include <wait_bit.h>
+
+#include "mscc_xfer.h"
+
+#define GCB_MIIM_MII_STATUS		0x0
+#define		GCB_MIIM_STAT_BUSY		BIT(3)
+#define GCB_MIIM_MII_CMD		0x8
+#define		GCB_MIIM_MII_CMD_OPR_WRITE	BIT(1)
+#define		GCB_MIIM_MII_CMD_OPR_READ	BIT(2)
+#define		GCB_MIIM_MII_CMD_WRDATA(x)	((x) << 4)
+#define		GCB_MIIM_MII_CMD_REGAD(x)	((x) << 20)
+#define		GCB_MIIM_MII_CMD_PHYAD(x)	((x) << 25)
+#define		GCB_MIIM_MII_CMD_VLD		BIT(31)
+#define GCB_MIIM_DATA			0xC
+#define		GCB_MIIM_DATA_ERROR		(0x3 << 16)
+
+#define PHY_CFG				0x0
+#define PHY_CFG_ENA				0x3
+#define PHY_CFG_COMMON_RST			BIT(2)
+#define PHY_CFG_RST				(0x3 << 3)
+#define PHY_STAT			0x4
+#define PHY_STAT_SUPERVISOR_COMPLETE		BIT(0)
+
+#define ANA_AC_RAM_CTRL_RAM_INIT		0x14fdc
+#define ANA_AC_STAT_GLOBAL_CFG_PORT_RESET	0x15474
+
+#define ANA_CL_PORT_VLAN_CFG(x)			(0xa018 + 0xc8 * (x))
+#define		ANA_CL_PORT_VLAN_CFG_AWARE_ENA			BIT(19)
+#define		ANA_CL_PORT_VLAN_CFG_POP_CNT(x)			((x) << 17)
+
+#define ANA_L2_COMMON_FWD_CFG			0x18498
+#define		ANA_L2_COMMON_FWD_CFG_CPU_DMAC_COPY_ENA	BIT(6)
+
+#define ASM_CFG_STAT_CFG			0xb08
+#define ASM_CFG_PORT(x)				(0xb74 + 0x4 * (x))
+#define		ASM_CFG_PORT_NO_PREAMBLE_ENA		BIT(8)
+#define		ASM_CFG_PORT_INJ_FORMAT_CFG(x)		((x) << 1)
+#define ASM_RAM_CTRL_RAM_INIT			0xbfc
+
+#define DEV_DEV_CFG_DEV_RST_CTRL	0x0
+#define		DEV_DEV_CFG_DEV_RST_CTRL_SPEED_SEL(x)	((x) << 20)
+#define DEV_MAC_CFG_MAC_ENA		0x24
+#define		DEV_MAC_CFG_MAC_ENA_RX_ENA		BIT(4)
+#define		DEV_MAC_CFG_MAC_ENA_TX_ENA		BIT(0)
+#define DEV_MAC_CFG_MAC_IFG		0x3c
+#define		DEV_MAC_CFG_MAC_IFG_TX_IFG(x)		((x) << 8)
+#define		DEV_MAC_CFG_MAC_IFG_RX_IFG2(x)		((x) << 4)
+#define		DEV_MAC_CFG_MAC_IFG_RX_IFG1(x)		(x)
+#define DEV_PCS1G_CFG_PCS1G_CFG		0x48
+#define		DEV_PCS1G_CFG_PCS1G_CFG_PCS_ENA		BIT(0)
+#define DEV_PCS1G_CFG_PCS1G_MODE	0x4c
+#define DEV_PCS1G_CFG_PCS1G_SD		0x50
+#define DEV_PCS1G_CFG_PCS1G_ANEG	0x54
+#define		DEV_PCS1G_CFG_PCS1G_ANEG_ADV_ABILITY(x)	((x) << 16)
+
+#define LRN_COMMON_ACCESS_CTRL			0x0
+#define		LRN_COMMON_ACCESS_CTRL_MAC_TABLE_ACCESS_SHOT	BIT(0)
+#define LRN_COMMON_MAC_ACCESS_CFG0		0x4
+#define LRN_COMMON_MAC_ACCESS_CFG1		0x8
+#define LRN_COMMON_MAC_ACCESS_CFG2		0xc
+#define		LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_ADDR(x)	(x)
+#define		LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_TYPE(x)	((x) << 12)
+#define		LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_VLD	BIT(15)
+#define		LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_LOCKED	BIT(16)
+#define		LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_COPY	BIT(23)
+#define		LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_QU(x)	((x) << 24)
+
+#define QFWD_SYSTEM_SWITCH_PORT_MODE(x)		(0x4400 + 0x4 * (x))
+#define		QFWD_SYSTEM_SWITCH_PORT_MODE_PORT_ENA		BIT(17)
+
+#define QS_XTR_GRP_CFG(x)		(4 * (x))
+#define QS_INJ_GRP_CFG(x)		(0x24 + (x) * 4)
+
+#define QSYS_SYSTEM_RESET_CFG			0x1048
+#define QSYS_CALCFG_CAL_AUTO			0x1134
+#define QSYS_CALCFG_CAL_CTRL			0x113c
+#define		QSYS_CALCFG_CAL_CTRL_CAL_MODE(x)		((x) << 11)
+#define QSYS_RAM_CTRL_RAM_INIT			0x1140
+
+#define REW_RAM_CTRL_RAM_INIT			0xFFF4
+
+#define MAC_VID			0
+#define CPU_PORT		11
+#define IFH_LEN			7
+#define ETH_ALEN		6
+#define PGID_BROADCAST		50
+#define PGID_UNICAST		51
+
+static const char * const regs_names[] = {
+	"port0", "port1",
+	"ana_ac", "ana_cl", "ana_l2", "asm", "lrn", "qfwd", "qs", "qsys", "rew",
+};
+
+#define REGS_NAMES_COUNT ARRAY_SIZE(regs_names) + 1
+#define MAX_PORT 2
+
+enum servalt_ctrl_regs {
+	ANA_AC = MAX_PORT,
+	ANA_CL,
+	ANA_L2,
+	ASM,
+	LRN,
+	QFWD,
+	QS,
+	QSYS,
+	REW,
+};
+
+#define SERVALT_MIIM_BUS_COUNT 2
+
+struct servalt_phy_port_t {
+	size_t phy_addr;
+	struct mii_dev *bus;
+};
+
+struct servalt_private {
+	void __iomem *regs[REGS_NAMES_COUNT];
+	struct mii_dev *bus[SERVALT_MIIM_BUS_COUNT];
+	struct servalt_phy_port_t ports[MAX_PORT];
+};
+
+struct mscc_miim_dev {
+	void __iomem *regs;
+	phys_addr_t miim_base;
+	unsigned long miim_size;
+	struct mii_dev *bus;
+};
+
+static const unsigned long servalt_regs_qs[] = {
+	[MSCC_QS_XTR_RD] = 0x8,
+	[MSCC_QS_XTR_FLUSH] = 0x18,
+	[MSCC_QS_XTR_DATA_PRESENT] = 0x1c,
+	[MSCC_QS_INJ_WR] = 0x2c,
+	[MSCC_QS_INJ_CTRL] = 0x34,
+};
+
+static struct mscc_miim_dev miim[SERVALT_MIIM_BUS_COUNT];
+static int miim_count = -1;
+
+static int mscc_miim_wait_ready(struct mscc_miim_dev *miim)
+{
+	return wait_for_bit_le32(miim->regs + GCB_MIIM_MII_STATUS,
+				 GCB_MIIM_STAT_BUSY, false, 250, false);
+}
+
+static int mscc_miim_read(struct mii_dev *bus, int addr, int devad, int reg)
+{
+	struct mscc_miim_dev *miim = (struct mscc_miim_dev *)bus->priv;
+	u32 val;
+	int ret;
+
+	ret = mscc_miim_wait_ready(miim);
+	if (ret)
+		goto out;
+
+	writel(GCB_MIIM_MII_CMD_VLD | GCB_MIIM_MII_CMD_PHYAD(addr) |
+	       GCB_MIIM_MII_CMD_REGAD(reg) | GCB_MIIM_MII_CMD_OPR_READ,
+	       miim->regs + GCB_MIIM_MII_CMD);
+
+	ret = mscc_miim_wait_ready(miim);
+	if (ret)
+		goto out;
+
+	val = readl(miim->regs + GCB_MIIM_DATA);
+	if (val & GCB_MIIM_DATA_ERROR) {
+		ret = -EIO;
+		goto out;
+	}
+
+	ret = val & 0xFFFF;
+out:
+	return ret;
+}
+
+static int mscc_miim_write(struct mii_dev *bus, int addr, int devad, int reg,
+			   u16 val)
+{
+	struct mscc_miim_dev *miim = (struct mscc_miim_dev *)bus->priv;
+	int ret;
+
+	ret = mscc_miim_wait_ready(miim);
+	if (ret < 0)
+		goto out;
+
+	writel(GCB_MIIM_MII_CMD_VLD | GCB_MIIM_MII_CMD_PHYAD(addr) |
+	       GCB_MIIM_MII_CMD_REGAD(reg) | GCB_MIIM_MII_CMD_WRDATA(val) |
+	       GCB_MIIM_MII_CMD_OPR_WRITE, miim->regs + GCB_MIIM_MII_CMD);
+
+out:
+	return ret;
+}
+
+static struct mii_dev *servalt_mdiobus_init(phys_addr_t miim_base,
+					    unsigned long miim_size)
+{
+	struct mii_dev *bus;
+
+	bus = mdio_alloc();
+	if (!bus)
+		return NULL;
+
+	++miim_count;
+	sprintf(bus->name, "miim-bus%d", miim_count);
+
+	miim[miim_count].regs = ioremap(miim_base, miim_size);
+	miim[miim_count].miim_base = miim_base;
+	miim[miim_count].miim_size = miim_size;
+	bus->priv = &miim[miim_count];
+	bus->read = mscc_miim_read;
+	bus->write = mscc_miim_write;
+
+	if (mdio_register(bus))
+		return NULL;
+
+	miim[miim_count].bus = bus;
+	return bus;
+}
+
+static void mscc_phy_reset(void)
+{
+	writel(0, BASE_DEVCPU_GCB + GCB_PHY_CFG + PHY_CFG);
+	writel(PHY_CFG_RST | PHY_CFG_COMMON_RST
+	       | PHY_CFG_ENA, BASE_DEVCPU_GCB + GCB_PHY_CFG + PHY_CFG);
+	if (wait_for_bit_le32((const void *)(BASE_DEVCPU_GCB + GCB_PHY_CFG) +
+			      PHY_STAT, PHY_STAT_SUPERVISOR_COMPLETE,
+			      true, 2000, false)) {
+		pr_err("Timeout in phy reset\n");
+	}
+}
+
+static void servalt_cpu_capture_setup(struct servalt_private *priv)
+{
+	/* ASM: No preamble and IFH prefix on CPU injected frames */
+	writel(ASM_CFG_PORT_NO_PREAMBLE_ENA |
+	       ASM_CFG_PORT_INJ_FORMAT_CFG(1),
+	       priv->regs[ASM] + ASM_CFG_PORT(CPU_PORT));
+
+	/* Set Manual injection via DEVCPU_QS registers for CPU queue 0 */
+	writel(0x5, priv->regs[QS] + QS_INJ_GRP_CFG(0));
+
+	/* Set Manual extraction via DEVCPU_QS registers for CPU queue 0 */
+	writel(0x7, priv->regs[QS] + QS_XTR_GRP_CFG(0));
+
+	/* Enable CPU port for any frame transfer */
+	setbits_le32(priv->regs[QFWD] + QFWD_SYSTEM_SWITCH_PORT_MODE(CPU_PORT),
+		     QFWD_SYSTEM_SWITCH_PORT_MODE_PORT_ENA);
+
+	/* Send a copy to CPU when found as forwarding entry */
+	setbits_le32(priv->regs[ANA_L2] + ANA_L2_COMMON_FWD_CFG,
+		     ANA_L2_COMMON_FWD_CFG_CPU_DMAC_COPY_ENA);
+}
+
+static void servalt_port_init(struct servalt_private *priv, int port)
+{
+	void __iomem *regs = priv->regs[port];
+
+	/* Enable PCS */
+	writel(DEV_PCS1G_CFG_PCS1G_CFG_PCS_ENA,
+	       regs + DEV_PCS1G_CFG_PCS1G_CFG);
+
+	/* Disable Signal Detect */
+	writel(0, regs + DEV_PCS1G_CFG_PCS1G_SD);
+
+	/* Enable MAC RX and TX */
+	writel(DEV_MAC_CFG_MAC_ENA_RX_ENA |
+	       DEV_MAC_CFG_MAC_ENA_TX_ENA,
+	       regs + DEV_MAC_CFG_MAC_ENA);
+
+	/* Clear sgmii_mode_ena */
+	writel(0, regs + DEV_PCS1G_CFG_PCS1G_MODE);
+
+	/*
+	 * Clear sw_resolve_ena(bit 0) and set adv_ability to
+	 * something meaningful just in case
+	 */
+	writel(DEV_PCS1G_CFG_PCS1G_ANEG_ADV_ABILITY(0x20),
+	       regs + DEV_PCS1G_CFG_PCS1G_ANEG);
+
+	/* Set MAC IFG Gaps */
+	writel(DEV_MAC_CFG_MAC_IFG_TX_IFG(4) |
+	       DEV_MAC_CFG_MAC_IFG_RX_IFG1(5) |
+	       DEV_MAC_CFG_MAC_IFG_RX_IFG2(1),
+	       regs + DEV_MAC_CFG_MAC_IFG);
+
+	/* Set link speed and release all resets */
+	writel(DEV_DEV_CFG_DEV_RST_CTRL_SPEED_SEL(2),
+	       regs + DEV_DEV_CFG_DEV_RST_CTRL);
+
+	/* Make VLAN aware for CPU traffic */
+	writel(ANA_CL_PORT_VLAN_CFG_AWARE_ENA |
+	       ANA_CL_PORT_VLAN_CFG_POP_CNT(1) |
+	       MAC_VID,
+	       priv->regs[ANA_CL] + ANA_CL_PORT_VLAN_CFG(port));
+
+	/* Enable CPU port for any frame transfer */
+	setbits_le32(priv->regs[QFWD] + QFWD_SYSTEM_SWITCH_PORT_MODE(port),
+		     QFWD_SYSTEM_SWITCH_PORT_MODE_PORT_ENA);
+}
+
+static int ram_init(u32 val, void __iomem *addr)
+{
+	writel(val, addr);
+
+	if (wait_for_bit_le32(addr, BIT(1), false, 2000, false)) {
+		printf("Timeout in memory reset, reg = 0x%08x\n", val);
+		return 1;
+	}
+
+	return 0;
+}
+
+static int servalt_switch_init(struct servalt_private *priv)
+{
+	/* Initialize memories */
+	ram_init(0x3, priv->regs[QSYS] + QSYS_RAM_CTRL_RAM_INIT);
+	ram_init(0x3, priv->regs[ASM] + ASM_RAM_CTRL_RAM_INIT);
+	ram_init(0x3, priv->regs[ANA_AC] + ANA_AC_RAM_CTRL_RAM_INIT);
+	ram_init(0x3, priv->regs[REW] + REW_RAM_CTRL_RAM_INIT);
+
+	/* Reset counters */
+	writel(0x1, priv->regs[ANA_AC] + ANA_AC_STAT_GLOBAL_CFG_PORT_RESET);
+	writel(0x1, priv->regs[ASM] + ASM_CFG_STAT_CFG);
+
+	/* Enable switch-core and queue system */
+	writel(0x1, priv->regs[QSYS] + QSYS_SYSTEM_RESET_CFG);
+
+	return 0;
+}
+
+static void servalt_switch_config(struct servalt_private *priv)
+{
+	writel(0x55555555, priv->regs[QSYS] + QSYS_CALCFG_CAL_AUTO);
+
+	writel(readl(priv->regs[QSYS] + QSYS_CALCFG_CAL_CTRL) |
+	       QSYS_CALCFG_CAL_CTRL_CAL_MODE(8),
+	       priv->regs[QSYS] + QSYS_CALCFG_CAL_CTRL);
+}
+
+static int servalt_initialize(struct servalt_private *priv)
+{
+	int ret, i;
+
+	/* Initialize switch memories, enable core */
+	ret = servalt_switch_init(priv);
+	if (ret)
+		return ret;
+
+	servalt_switch_config(priv);
+
+	for (i = 0; i < MAX_PORT; i++)
+		servalt_port_init(priv, i);
+
+	servalt_cpu_capture_setup(priv);
+
+	return 0;
+}
+
+static inline
+int servalt_vlant_wait_for_completion(struct servalt_private *priv)
+{
+	if (wait_for_bit_le32(priv->regs[LRN] + LRN_COMMON_ACCESS_CTRL,
+			      LRN_COMMON_ACCESS_CTRL_MAC_TABLE_ACCESS_SHOT,
+			      false, 2000, false))
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+static int servalt_mac_table_add(struct servalt_private *priv,
+				 const unsigned char mac[ETH_ALEN], int pgid)
+{
+	u32 macl = 0, mach = 0;
+
+	/*
+	 * Set the MAC address to handle and the vlan associated in a format
+	 * understood by the hardware.
+	 */
+	mach |= MAC_VID << 16;
+	mach |= ((u32)mac[0]) << 8;
+	mach |= ((u32)mac[1]) << 0;
+	macl |= ((u32)mac[2]) << 24;
+	macl |= ((u32)mac[3]) << 16;
+	macl |= ((u32)mac[4]) << 8;
+	macl |= ((u32)mac[5]) << 0;
+
+	writel(mach, priv->regs[LRN] + LRN_COMMON_MAC_ACCESS_CFG0);
+	writel(macl, priv->regs[LRN] + LRN_COMMON_MAC_ACCESS_CFG1);
+
+	writel(LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_ADDR(pgid) |
+	       LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_TYPE(0x3) |
+	       LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_COPY |
+	       LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_QU(0) |
+	       LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_VLD |
+	       LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_LOCKED,
+	       priv->regs[LRN] + LRN_COMMON_MAC_ACCESS_CFG2);
+
+	writel(LRN_COMMON_ACCESS_CTRL_MAC_TABLE_ACCESS_SHOT,
+	       priv->regs[LRN] + LRN_COMMON_ACCESS_CTRL);
+
+	return servalt_vlant_wait_for_completion(priv);
+}
+
+static int servalt_write_hwaddr(struct udevice *dev)
+{
+	struct servalt_private *priv = dev_get_priv(dev);
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+
+	return servalt_mac_table_add(priv, pdata->enetaddr, PGID_UNICAST);
+}
+
+static int servalt_start(struct udevice *dev)
+{
+	struct servalt_private *priv = dev_get_priv(dev);
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	const unsigned char mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff };
+	int ret;
+
+	ret = servalt_initialize(priv);
+	if (ret)
+		return ret;
+
+	/* Set MAC address tables entries for CPU redirection */
+	ret = servalt_mac_table_add(priv, mac, PGID_BROADCAST);
+	if (ret)
+		return ret;
+
+	ret = servalt_mac_table_add(priv, pdata->enetaddr, PGID_UNICAST);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static void servalt_stop(struct udevice *dev)
+{
+}
+
+static int servalt_send(struct udevice *dev, void *packet, int length)
+{
+	struct servalt_private *priv = dev_get_priv(dev);
+	u32 ifh[IFH_LEN];
+	u32 *buf = packet;
+
+	memset(ifh, '\0', IFH_LEN * 4);
+
+	/* Set DST PORT_MASK */
+	ifh[0] = htonl(0);
+	ifh[1] = htonl(0x1FFFFF);
+	ifh[2] = htonl(~0);
+	/* Set DST_MODE to INJECT and UPDATE_FCS */
+	ifh[5] = htonl(0x4c0);
+
+	return mscc_send(priv->regs[QS], servalt_regs_qs,
+			 ifh, IFH_LEN, buf, length);
+}
+
+static int servalt_recv(struct udevice *dev, int flags, uchar **packetp)
+{
+	struct servalt_private *priv = dev_get_priv(dev);
+	u32 *rxbuf = (u32 *)net_rx_packets[0];
+	int byte_cnt = 0;
+
+	byte_cnt = mscc_recv(priv->regs[QS], servalt_regs_qs, rxbuf, IFH_LEN,
+			     false);
+
+	*packetp = net_rx_packets[0];
+
+	return byte_cnt;
+}
+
+static struct mii_dev *get_mdiobus(phys_addr_t base, unsigned long size)
+{
+	int i = 0;
+
+	for (i = 0; i < SERVALT_MIIM_BUS_COUNT; ++i)
+		if (miim[i].miim_base == base && miim[i].miim_size == size)
+			return miim[i].bus;
+
+	return NULL;
+}
+
+static void add_port_entry(struct servalt_private *priv, size_t index,
+			   size_t phy_addr, struct mii_dev *bus)
+{
+	priv->ports[index].phy_addr = phy_addr;
+	priv->ports[index].bus = bus;
+}
+
+static int servalt_probe(struct udevice *dev)
+{
+	struct servalt_private *priv = dev_get_priv(dev);
+	int i;
+	struct resource res;
+	fdt32_t faddr;
+	phys_addr_t addr_base;
+	unsigned long addr_size;
+	ofnode eth_node, node, mdio_node;
+	size_t phy_addr;
+	struct mii_dev *bus;
+	struct ofnode_phandle_args phandle;
+
+	if (!priv)
+		return -EINVAL;
+
+	/* Get registers and map them to the private structure */
+	for (i = 0; i < ARRAY_SIZE(regs_names); i++) {
+		priv->regs[i] = dev_remap_addr_name(dev, regs_names[i]);
+		if (!priv->regs[i]) {
+			debug
+			    ("Error can't get regs base addresses for %s\n",
+			     regs_names[i]);
+			return -ENOMEM;
+		}
+	}
+
+	/* Initialize miim buses */
+	memset(&miim, 0x0, sizeof(struct mscc_miim_dev) *
+	       SERVALT_MIIM_BUS_COUNT);
+
+	/* iterate all the ports and find out on which bus they are */
+	i = 0;
+	eth_node = dev_read_first_subnode(dev);
+	for (node = ofnode_first_subnode(eth_node);
+	     ofnode_valid(node);
+	     node = ofnode_next_subnode(node)) {
+		if (ofnode_read_resource(node, 0, &res))
+			return -ENOMEM;
+		i = res.start;
+
+		ofnode_parse_phandle_with_args(node, "phy-handle", NULL, 0, 0,
+					       &phandle);
+
+		/* Get phy address on mdio bus */
+		if (ofnode_read_resource(phandle.node, 0, &res))
+			return -ENOMEM;
+		phy_addr = res.start;
+
+		/* Get mdio node */
+		mdio_node = ofnode_get_parent(phandle.node);
+
+		if (ofnode_read_resource(mdio_node, 0, &res))
+			return -ENOMEM;
+		faddr = cpu_to_fdt32(res.start);
+
+		addr_base = ofnode_translate_address(mdio_node, &faddr);
+		addr_size = res.end - res.start;
+
+		/* If the bus is new then create a new bus */
+		if (!get_mdiobus(addr_base, addr_size))
+			priv->bus[miim_count] =
+				servalt_mdiobus_init(addr_base, addr_size);
+
+		/* Connect mdio bus with the port */
+		bus = get_mdiobus(addr_base, addr_size);
+		add_port_entry(priv, i, phy_addr, bus);
+	}
+
+	mscc_phy_reset();
+
+	for (i = 0; i < MAX_PORT; i++) {
+		if (!priv->ports[i].bus)
+			continue;
+
+		phy_connect(priv->ports[i].bus, priv->ports[i].phy_addr, dev,
+			    PHY_INTERFACE_MODE_NONE);
+	}
+
+	return 0;
+}
+
+static int servalt_remove(struct udevice *dev)
+{
+	struct servalt_private *priv = dev_get_priv(dev);
+	int i;
+
+	for (i = 0; i < SERVALT_MIIM_BUS_COUNT; i++) {
+		mdio_unregister(priv->bus[i]);
+		mdio_free(priv->bus[i]);
+	}
+
+	return 0;
+}
+
+static const struct eth_ops servalt_ops = {
+	.start        = servalt_start,
+	.stop         = servalt_stop,
+	.send         = servalt_send,
+	.recv         = servalt_recv,
+	.write_hwaddr = servalt_write_hwaddr,
+};
+
+static const struct udevice_id mscc_servalt_ids[] = {
+	{.compatible = "mscc,vsc7437-switch" },
+	{ /* Sentinel */ }
+};
+
+U_BOOT_DRIVER(servalt) = {
+	.name				= "servalt-switch",
+	.id				= UCLASS_ETH,
+	.of_match			= mscc_servalt_ids,
+	.probe				= servalt_probe,
+	.remove				= servalt_remove,
+	.ops				= &servalt_ops,
+	.priv_auto_alloc_size		= sizeof(struct servalt_private),
+	.platdata_auto_alloc_size	= sizeof(struct eth_pdata),
+};
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 32bbf41..102fb91 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -174,4 +174,12 @@
 
 	  This PHY is found on some Keystone (K2) devices supporting USB.
 
+config MT76X8_USB_PHY
+	bool "MediaTek MT76x8 (7628/88) USB PHY support"
+	depends on PHY
+	help
+          Support the USB PHY in MT76x8 SoCs
+
+	  This PHY is found on MT76x8 devices supporting USB.
+
 endmenu
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index 099551d..b55917b 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -19,3 +19,4 @@
 obj-$(CONFIG_MSM8916_USB_PHY) += msm8916-usbh-phy.o
 obj-$(CONFIG_OMAP_USB2_PHY) += omap-usb2-phy.o
 obj-$(CONFIG_KEYSTONE_USB_PHY) += keystone-usb-phy.o
+obj-$(CONFIG_MT76X8_USB_PHY) += mt76x8-usb-phy.o
diff --git a/drivers/phy/mt76x8-usb-phy.c b/drivers/phy/mt76x8-usb-phy.c
new file mode 100644
index 0000000..268da8e
--- /dev/null
+++ b/drivers/phy/mt76x8-usb-phy.c
@@ -0,0 +1,161 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Stefan Roese <sr@denx.de>
+ *
+ * Derived from linux/drivers/phy/ralink/phy-ralink-usb.c
+ *     Copyright (C) 2017 John Crispin <john@phrozen.org>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <generic-phy.h>
+#include <regmap.h>
+#include <reset-uclass.h>
+#include <syscon.h>
+#include <asm/io.h>
+
+#define RT_SYSC_REG_SYSCFG1		0x014
+#define RT_SYSC_REG_CLKCFG1		0x030
+#define RT_SYSC_REG_USB_PHY_CFG		0x05c
+
+#define OFS_U2_PHY_AC0			0x800
+#define OFS_U2_PHY_AC1			0x804
+#define OFS_U2_PHY_AC2			0x808
+#define OFS_U2_PHY_ACR0			0x810
+#define OFS_U2_PHY_ACR1			0x814
+#define OFS_U2_PHY_ACR2			0x818
+#define OFS_U2_PHY_ACR3			0x81C
+#define OFS_U2_PHY_ACR4			0x820
+#define OFS_U2_PHY_AMON0		0x824
+#define OFS_U2_PHY_DCR0			0x860
+#define OFS_U2_PHY_DCR1			0x864
+#define OFS_U2_PHY_DTM0			0x868
+#define OFS_U2_PHY_DTM1			0x86C
+
+#define RT_RSTCTRL_UDEV			BIT(25)
+#define RT_RSTCTRL_UHST			BIT(22)
+#define RT_SYSCFG1_USB0_HOST_MODE	BIT(10)
+
+#define MT7620_CLKCFG1_UPHY0_CLK_EN	BIT(25)
+#define MT7620_CLKCFG1_UPHY1_CLK_EN	BIT(22)
+#define RT_CLKCFG1_UPHY1_CLK_EN		BIT(20)
+#define RT_CLKCFG1_UPHY0_CLK_EN		BIT(18)
+
+#define USB_PHY_UTMI_8B60M		BIT(1)
+#define UDEV_WAKEUP			BIT(0)
+
+struct mt76x8_usb_phy {
+	u32			clk;
+	void __iomem		*base;
+	struct regmap		*sysctl;
+};
+
+static void u2_phy_w32(struct mt76x8_usb_phy *phy, u32 val, u32 reg)
+{
+	writel(val, phy->base + reg);
+}
+
+static u32 u2_phy_r32(struct mt76x8_usb_phy *phy, u32 reg)
+{
+	return readl(phy->base + reg);
+}
+
+static void mt76x8_usb_phy_init(struct mt76x8_usb_phy *phy)
+{
+	u2_phy_r32(phy, OFS_U2_PHY_AC2);
+	u2_phy_r32(phy, OFS_U2_PHY_ACR0);
+	u2_phy_r32(phy, OFS_U2_PHY_DCR0);
+
+	u2_phy_w32(phy, 0x00ffff02, OFS_U2_PHY_DCR0);
+	u2_phy_r32(phy, OFS_U2_PHY_DCR0);
+	u2_phy_w32(phy, 0x00555502, OFS_U2_PHY_DCR0);
+	u2_phy_r32(phy, OFS_U2_PHY_DCR0);
+	u2_phy_w32(phy, 0x00aaaa02, OFS_U2_PHY_DCR0);
+	u2_phy_r32(phy, OFS_U2_PHY_DCR0);
+	u2_phy_w32(phy, 0x00000402, OFS_U2_PHY_DCR0);
+	u2_phy_r32(phy, OFS_U2_PHY_DCR0);
+	u2_phy_w32(phy, 0x0048086a, OFS_U2_PHY_AC0);
+	u2_phy_w32(phy, 0x4400001c, OFS_U2_PHY_AC1);
+	u2_phy_w32(phy, 0xc0200000, OFS_U2_PHY_ACR3);
+	u2_phy_w32(phy, 0x02000000, OFS_U2_PHY_DTM0);
+}
+
+static int mt76x8_usb_phy_power_on(struct phy *_phy)
+{
+	struct mt76x8_usb_phy *phy = dev_get_priv(_phy->dev);
+	u32 t;
+
+	/* enable the phy */
+	regmap_update_bits(phy->sysctl, RT_SYSC_REG_CLKCFG1,
+			   phy->clk, phy->clk);
+
+	/* setup host mode */
+	regmap_update_bits(phy->sysctl, RT_SYSC_REG_SYSCFG1,
+			   RT_SYSCFG1_USB0_HOST_MODE,
+			   RT_SYSCFG1_USB0_HOST_MODE);
+
+	/*
+	 * The SDK kernel had a delay of 100ms. however on device
+	 * testing showed that 10ms is enough
+	 */
+	mdelay(10);
+
+	if (phy->base)
+		mt76x8_usb_phy_init(phy);
+
+	/* print some status info */
+	regmap_read(phy->sysctl, RT_SYSC_REG_USB_PHY_CFG, &t);
+	printf("remote usb device wakeup %s\n",
+	       (t & UDEV_WAKEUP) ? "enabled" : "disabled");
+	if (t & USB_PHY_UTMI_8B60M)
+		printf("UTMI 8bit 60MHz\n");
+	else
+		printf("UTMI 16bit 30MHz\n");
+
+	return 0;
+}
+
+static int mt76x8_usb_phy_power_off(struct phy *_phy)
+{
+	struct mt76x8_usb_phy *phy = dev_get_priv(_phy->dev);
+
+	/* disable the phy */
+	regmap_update_bits(phy->sysctl, RT_SYSC_REG_CLKCFG1,
+			   phy->clk, 0);
+
+	return 0;
+}
+
+static int mt76x8_usb_phy_probe(struct udevice *dev)
+{
+	struct mt76x8_usb_phy *phy = dev_get_priv(dev);
+
+	phy->sysctl = syscon_regmap_lookup_by_phandle(dev, "ralink,sysctl");
+	if (IS_ERR(phy->sysctl))
+		return PTR_ERR(phy->sysctl);
+
+	phy->base = dev_read_addr_ptr(dev);
+	if (!phy->base)
+		return -EINVAL;
+
+	return 0;
+}
+
+static struct phy_ops mt76x8_usb_phy_ops = {
+	.power_on = mt76x8_usb_phy_power_on,
+	.power_off = mt76x8_usb_phy_power_off,
+};
+
+static const struct udevice_id mt76x8_usb_phy_ids[] = {
+	{ .compatible = "mediatek,mt7628-usbphy" },
+	{ }
+};
+
+U_BOOT_DRIVER(mt76x8_usb_phy) = {
+	.name		= "mt76x8_usb_phy",
+	.id		= UCLASS_PHY,
+	.of_match	= mt76x8_usb_phy_ids,
+	.ops		= &mt76x8_usb_phy_ops,
+	.probe		= mt76x8_usb_phy_probe,
+	.priv_auto_alloc_size = sizeof(struct mt76x8_usb_phy),
+};
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index be709f7..a0ac167 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -209,6 +209,25 @@
 	  the GPIO definitions and pin control functions for each available
 	  multiplex function.
 
+config PINCTRL_STMFX
+	bool "STMicroelectronics STMFX I2C GPIO expander pinctrl driver"
+	depends on DM && PINCTRL_FULL
+	help
+	  I2C driver for STMicroelectronics Multi-Function eXpander (STMFX)
+	  GPIO expander.
+	  Supports pin multiplexing control on stm32 SoCs.
+
+	  The driver is controlled by a device tree node which contains both
+	  the GPIO definitions and pin control functions for each available
+	  multiplex function.
+
+config SPL_PINCTRL_STMFX
+	bool "STMicroelectronics STMFX I2C GPIO expander pinctrl driver in SPL"
+	depends on SPL_PINCTRL_FULL
+	help
+	  This option is an SPL-variant of the SPL_PINCTRL_STMFX option.
+	  See the help of PINCTRL_STMFX for details.
+
 config ASPEED_AST2500_PINCTRL
   bool "Aspeed AST2500 pin control driver"
   depends on DM && PINCTRL_GENERIC && ASPEED_AST2500
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index e2c2b15..4b080b7 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -22,4 +22,5 @@
 obj-$(CONFIG_PINCTRL_SINGLE)	+= pinctrl-single.o
 obj-$(CONFIG_PINCTRL_STI)	+= pinctrl-sti.o
 obj-$(CONFIG_PINCTRL_STM32)	+= pinctrl_stm32.o
+obj-$(CONFIG_$(SPL_)PINCTRL_STMFX)	+= pinctrl-stmfx.o
 obj-y				+= broadcom/
diff --git a/drivers/pinctrl/ath79/Makefile b/drivers/pinctrl/ath79/Makefile
index 1daa212..c7d1e44 100644
--- a/drivers/pinctrl/ath79/Makefile
+++ b/drivers/pinctrl/ath79/Makefile
@@ -1,4 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0+
 
 obj-$(CONFIG_PINCTRL_AR933X) += pinctrl_ar933x.o
-obj-$(CONFIG_PINCTRL_QCA953x) += pinctrl_qca953x.o
+obj-$(CONFIG_PINCTRL_QCA953X) += pinctrl_qca953x.o
diff --git a/drivers/pinctrl/pinctrl-stmfx.c b/drivers/pinctrl/pinctrl-stmfx.c
new file mode 100644
index 0000000..5431df9
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-stmfx.c
@@ -0,0 +1,431 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+ *
+ * Driver for STMicroelectronics Multi-Function eXpander (STMFX) GPIO expander
+ * based on Linux driver : pinctrl/pinctrl-stmfx.c
+ */
+#include <common.h>
+#include <dm.h>
+#include <i2c.h>
+#include <asm/gpio.h>
+#include <dm/device.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <dm/pinctrl.h>
+#include <linux/bitfield.h>
+#include <power/regulator.h>
+
+/* STMFX pins = GPIO[15:0] + aGPIO[7:0] */
+#define STMFX_MAX_GPIO			16
+#define STMFX_MAX_AGPIO			8
+
+/* General */
+#define STMFX_REG_CHIP_ID		0x00 /* R */
+#define STMFX_REG_FW_VERSION_MSB	0x01 /* R */
+#define STMFX_REG_FW_VERSION_LSB	0x02 /* R */
+#define STMFX_REG_SYS_CTRL		0x40 /* RW */
+
+/* MFX boot time is around 10ms, so after reset, we have to wait this delay */
+#define STMFX_BOOT_TIME_MS 10
+
+/* GPIOs expander */
+/* GPIO_STATE1 0x10, GPIO_STATE2 0x11, GPIO_STATE3 0x12 */
+#define STMFX_REG_GPIO_STATE		0x10 /* R */
+/* GPIO_DIR1 0x60, GPIO_DIR2 0x61, GPIO_DIR3 0x63 */
+#define STMFX_REG_GPIO_DIR		0x60 /* RW */
+/* GPIO_TYPE1 0x64, GPIO_TYPE2 0x65, GPIO_TYPE3 0x66 */
+#define STMFX_REG_GPIO_TYPE		0x64 /* RW */
+/* GPIO_PUPD1 0x68, GPIO_PUPD2 0x69, GPIO_PUPD3 0x6A */
+#define STMFX_REG_GPIO_PUPD		0x68 /* RW */
+/* GPO_SET1 0x6C, GPO_SET2 0x6D, GPO_SET3 0x6E */
+#define STMFX_REG_GPO_SET		0x6C /* RW */
+/* GPO_CLR1 0x70, GPO_CLR2 0x71, GPO_CLR3 0x72 */
+#define STMFX_REG_GPO_CLR		0x70 /* RW */
+
+/* STMFX_REG_CHIP_ID bitfields */
+#define STMFX_REG_CHIP_ID_MASK		GENMASK(7, 0)
+
+/* STMFX_REG_SYS_CTRL bitfields */
+#define STMFX_REG_SYS_CTRL_GPIO_EN	BIT(0)
+#define STMFX_REG_SYS_CTRL_ALTGPIO_EN	BIT(3)
+#define STMFX_REG_SYS_CTRL_SWRST	BIT(7)
+
+#define NR_GPIO_REGS			3
+#define NR_GPIOS_PER_REG		8
+#define get_reg(offset)			((offset) / NR_GPIOS_PER_REG)
+#define get_shift(offset)		((offset) % NR_GPIOS_PER_REG)
+#define get_mask(offset)		(BIT(get_shift(offset)))
+
+struct stmfx_pinctrl {
+	struct udevice *gpio;
+};
+
+static int stmfx_read(struct udevice *dev, uint offset)
+{
+	return  dm_i2c_reg_read(dev_get_parent(dev), offset);
+}
+
+static int stmfx_write(struct udevice *dev, uint offset, unsigned int val)
+{
+	return dm_i2c_reg_write(dev_get_parent(dev), offset, val);
+}
+
+static int stmfx_gpio_get(struct udevice *dev, unsigned int offset)
+{
+	u32 reg = STMFX_REG_GPIO_STATE + get_reg(offset);
+	u32 mask = get_mask(offset);
+	int ret;
+
+	ret = stmfx_read(dev, reg);
+
+	return ret < 0 ? ret : !!(ret & mask);
+}
+
+static int stmfx_gpio_set(struct udevice *dev, unsigned int offset, int value)
+{
+	u32 reg = value ? STMFX_REG_GPO_SET : STMFX_REG_GPO_CLR;
+	u32 mask = get_mask(offset);
+
+	return stmfx_write(dev, reg + get_reg(offset), mask);
+}
+
+static int stmfx_gpio_get_function(struct udevice *dev, unsigned int offset)
+{
+	u32 reg = STMFX_REG_GPIO_DIR + get_reg(offset);
+	u32 mask = get_mask(offset);
+	int ret;
+
+	ret = stmfx_read(dev, reg);
+
+	if (ret < 0)
+		return ret;
+	/* On stmfx, gpio pins direction is (0)input, (1)output. */
+
+	return ret & mask ? GPIOF_OUTPUT : GPIOF_INPUT;
+}
+
+static int stmfx_gpio_direction_input(struct udevice *dev, unsigned int offset)
+{
+	u32 reg = STMFX_REG_GPIO_DIR + get_reg(offset);
+	u32 mask = get_mask(offset);
+	int ret;
+
+	ret = stmfx_read(dev, reg);
+	if (ret < 0)
+		return ret;
+
+	ret &= ~mask;
+
+	return stmfx_write(dev, reg, ret & ~mask);
+}
+
+static int stmfx_gpio_direction_output(struct udevice *dev,
+				       unsigned int offset, int value)
+{
+	u32 reg = STMFX_REG_GPIO_DIR + get_reg(offset);
+	u32 mask = get_mask(offset);
+	int ret;
+
+	ret = stmfx_gpio_set(dev, offset, value);
+	if (ret < 0)
+		return ret;
+
+	ret = stmfx_read(dev, reg);
+	if (ret < 0)
+		return ret;
+
+	return stmfx_write(dev, reg, ret | mask);
+}
+
+static int stmfx_gpio_probe(struct udevice *dev)
+{
+	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+	struct ofnode_phandle_args args;
+	u8 sys_ctrl;
+
+	uc_priv->bank_name = "stmfx";
+	uc_priv->gpio_count = STMFX_MAX_GPIO + STMFX_MAX_AGPIO;
+	if (!dev_read_phandle_with_args(dev, "gpio-ranges",
+					NULL, 3, 0, &args)) {
+		uc_priv->gpio_count = args.args[2];
+	}
+
+	/* enable GPIO function */
+	sys_ctrl = STMFX_REG_SYS_CTRL_GPIO_EN;
+	if (uc_priv->gpio_count > STMFX_MAX_GPIO)
+		sys_ctrl |= STMFX_REG_SYS_CTRL_ALTGPIO_EN;
+	stmfx_write(dev, STMFX_REG_SYS_CTRL, sys_ctrl);
+
+	return 0;
+}
+
+static const struct dm_gpio_ops stmfx_gpio_ops = {
+	.set_value = stmfx_gpio_set,
+	.get_value = stmfx_gpio_get,
+	.get_function = stmfx_gpio_get_function,
+	.direction_input = stmfx_gpio_direction_input,
+	.direction_output = stmfx_gpio_direction_output,
+};
+
+U_BOOT_DRIVER(stmfx_gpio) = {
+	.name	= "stmfx-gpio",
+	.id	= UCLASS_GPIO,
+	.probe	= stmfx_gpio_probe,
+	.ops	= &stmfx_gpio_ops,
+};
+
+#if CONFIG_IS_ENABLED(PINCONF)
+static const struct pinconf_param stmfx_pinctrl_conf_params[] = {
+	{ "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
+	{ "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 0 },
+	{ "bias-pull-pin-default", PIN_CONFIG_BIAS_PULL_PIN_DEFAULT, 0 },
+	{ "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 0 },
+	{ "drive-open-drain", PIN_CONFIG_DRIVE_OPEN_DRAIN, 0 },
+	{ "drive-push-pull", PIN_CONFIG_DRIVE_PUSH_PULL, 0 },
+	{ "output-high", PIN_CONFIG_OUTPUT, 1 },
+	{ "output-low", PIN_CONFIG_OUTPUT, 0 },
+};
+
+static int stmfx_pinctrl_set_pupd(struct udevice *dev,
+				  unsigned int pin, u32 pupd)
+{
+	u8 reg = STMFX_REG_GPIO_PUPD + get_reg(pin);
+	u32 mask = get_mask(pin);
+	int ret;
+
+	ret = stmfx_read(dev, reg);
+	if (ret < 0)
+		return ret;
+	ret = (ret & ~mask) | (pupd ? mask : 0);
+
+	return stmfx_write(dev, reg, ret);
+}
+
+static int stmfx_pinctrl_set_type(struct udevice *dev,
+				  unsigned int pin, u32 type)
+{
+	u8 reg = STMFX_REG_GPIO_TYPE + get_reg(pin);
+	u32 mask = get_mask(pin);
+	int ret;
+
+	ret = stmfx_read(dev, reg);
+	if (ret < 0)
+		return ret;
+	ret = (ret & ~mask) | (type ? mask : 0);
+
+	return stmfx_write(dev, reg, ret);
+}
+
+static int stmfx_pinctrl_conf_set(struct udevice *dev, unsigned int pin,
+				  unsigned int param, unsigned int arg)
+{
+	int ret, dir;
+	struct stmfx_pinctrl *plat = dev_get_platdata(dev);
+
+	dir = stmfx_gpio_get_function(plat->gpio, pin);
+
+	if (dir < 0)
+		return dir;
+
+	switch (param) {
+	case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
+	case PIN_CONFIG_BIAS_DISABLE:
+	case PIN_CONFIG_BIAS_PULL_DOWN:
+		ret = stmfx_pinctrl_set_pupd(dev, pin, 0);
+		break;
+	case PIN_CONFIG_BIAS_PULL_UP:
+		ret = stmfx_pinctrl_set_pupd(dev, pin, 1);
+		break;
+	case PIN_CONFIG_DRIVE_OPEN_DRAIN:
+		if (dir == GPIOF_OUTPUT)
+			ret = stmfx_pinctrl_set_type(dev, pin, 1);
+		else
+			ret = stmfx_pinctrl_set_type(dev, pin, 0);
+		break;
+	case PIN_CONFIG_DRIVE_PUSH_PULL:
+		if (dir == GPIOF_OUTPUT)
+			ret = stmfx_pinctrl_set_type(dev, pin, 0);
+		else
+			ret = stmfx_pinctrl_set_type(dev, pin, 1);
+		break;
+	case PIN_CONFIG_OUTPUT:
+		ret = stmfx_gpio_direction_output(plat->gpio, pin, arg);
+		break;
+	default:
+		return -ENOTSUPP;
+	}
+
+	return ret;
+}
+#endif
+
+static int stmfx_pinctrl_get_pins_count(struct udevice *dev)
+{
+	struct stmfx_pinctrl *plat = dev_get_platdata(dev);
+	struct gpio_dev_priv *uc_priv;
+
+	uc_priv = dev_get_uclass_priv(plat->gpio);
+
+	return uc_priv->gpio_count;
+}
+
+/*
+ * STMFX pins[15:0] are called "gpio[15:0]"
+ * and STMFX pins[23:16] are called "agpio[7:0]"
+ */
+#define MAX_PIN_NAME_LEN 7
+static char pin_name[MAX_PIN_NAME_LEN];
+static const char *stmfx_pinctrl_get_pin_name(struct udevice *dev,
+					      unsigned int selector)
+{
+	if (selector < STMFX_MAX_GPIO)
+		snprintf(pin_name, MAX_PIN_NAME_LEN, "gpio%u", selector);
+	else
+		snprintf(pin_name, MAX_PIN_NAME_LEN, "agpio%u", selector - 16);
+	return pin_name;
+}
+
+static int stmfx_pinctrl_get_pin_muxing(struct udevice *dev,
+					unsigned int selector,
+					char *buf, int size)
+{
+	struct stmfx_pinctrl *plat = dev_get_platdata(dev);
+	int func;
+
+	func = stmfx_gpio_get_function(plat->gpio, selector);
+	if (func < 0)
+		return func;
+
+	snprintf(buf, size, "%s", func == GPIOF_INPUT ? "input" : "output");
+
+	return 0;
+}
+
+static int stmfx_pinctrl_bind(struct udevice *dev)
+{
+	struct stmfx_pinctrl *plat = dev_get_platdata(dev);
+
+	return device_bind_driver_to_node(dev->parent,
+					  "stmfx-gpio", "stmfx-gpio",
+					  dev_ofnode(dev), &plat->gpio);
+};
+
+static int stmfx_pinctrl_probe(struct udevice *dev)
+{
+	struct stmfx_pinctrl *plat = dev_get_platdata(dev);
+
+	return device_probe(plat->gpio);
+};
+
+const struct pinctrl_ops stmfx_pinctrl_ops = {
+	.get_pins_count = stmfx_pinctrl_get_pins_count,
+	.get_pin_name = stmfx_pinctrl_get_pin_name,
+	.set_state = pinctrl_generic_set_state,
+	.get_pin_muxing	= stmfx_pinctrl_get_pin_muxing,
+#if CONFIG_IS_ENABLED(PINCONF)
+	.pinconf_set = stmfx_pinctrl_conf_set,
+	.pinconf_num_params = ARRAY_SIZE(stmfx_pinctrl_conf_params),
+	.pinconf_params = stmfx_pinctrl_conf_params,
+#endif
+};
+
+static const struct udevice_id stmfx_pinctrl_match[] = {
+	{ .compatible = "st,stmfx-0300-pinctrl", },
+};
+
+U_BOOT_DRIVER(stmfx_pinctrl) = {
+	.name = "stmfx-pinctrl",
+	.id = UCLASS_PINCTRL,
+	.of_match = of_match_ptr(stmfx_pinctrl_match),
+	.bind = stmfx_pinctrl_bind,
+	.probe = stmfx_pinctrl_probe,
+	.ops = &stmfx_pinctrl_ops,
+	.platdata_auto_alloc_size = sizeof(struct stmfx_pinctrl),
+};
+
+static int stmfx_chip_init(struct udevice *dev)
+{
+	u8 id;
+	u8 version[2];
+	int ret;
+	struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
+
+	id = dm_i2c_reg_read(dev, STMFX_REG_CHIP_ID);
+	if (id < 0) {
+		dev_err(dev, "error reading chip id: %d\n", id);
+		return ret;
+	}
+	/*
+	 * Check that ID is the complement of the I2C address:
+	 * STMFX I2C address follows the 7-bit format (MSB), that's why
+	 * client->addr is shifted.
+	 *
+	 * STMFX_I2C_ADDR|       STMFX         |        Linux
+	 *   input pin   | I2C device address  | I2C device address
+	 *---------------------------------------------------------
+	 *       0       | b: 1000 010x h:0x84 |       0x42
+	 *       1       | b: 1000 011x h:0x86 |       0x43
+	 */
+	if (FIELD_GET(STMFX_REG_CHIP_ID_MASK, ~id) != (chip->chip_addr << 1)) {
+		dev_err(dev, "unknown chip id: %#x\n", id);
+		return -EINVAL;
+	}
+
+	ret = dm_i2c_read(dev, STMFX_REG_FW_VERSION_MSB,
+			  version, sizeof(version));
+	if (ret) {
+		dev_err(dev, "error reading fw version: %d\n", ret);
+		return ret;
+	}
+
+	dev_info(dev, "STMFX id: %#x, fw version: %x.%02x\n",
+		 id, version[0], version[1]);
+
+	ret = dm_i2c_reg_read(dev, STMFX_REG_SYS_CTRL);
+
+	if (ret < 0)
+		return ret;
+
+	ret = dm_i2c_reg_write(dev, STMFX_REG_SYS_CTRL,
+			       ret | STMFX_REG_SYS_CTRL_SWRST);
+	if (ret)
+		return ret;
+
+	mdelay(STMFX_BOOT_TIME_MS);
+
+	return ret;
+}
+
+static int stmfx_probe(struct udevice *dev)
+{
+	struct udevice *vdd;
+	int ret;
+
+	ret = device_get_supply_regulator(dev, "vdd-supply", &vdd);
+	if (ret && ret != -ENOENT) {
+		dev_err(dev, "vdd regulator error:%d\n", ret);
+		return ret;
+	}
+	if (!ret) {
+		ret = regulator_set_enable(vdd, true);
+		if (ret) {
+			dev_err(dev, "vdd enable failed: %d\n", ret);
+			return ret;
+		}
+	}
+
+	return stmfx_chip_init(dev);
+}
+
+static const struct udevice_id stmfx_match[] = {
+	{ .compatible = "st,stmfx-0300", },
+};
+
+U_BOOT_DRIVER(stmfx) = {
+	.name = "stmfx",
+	.id = UCLASS_I2C_GENERIC,
+	.of_match = of_match_ptr(stmfx_match),
+	.probe = stmfx_probe,
+	.bind = dm_scan_fdt_dev,
+};
diff --git a/drivers/pinctrl/pinctrl-uclass.c b/drivers/pinctrl/pinctrl-uclass.c
index 0e3260a..0e6c559 100644
--- a/drivers/pinctrl/pinctrl-uclass.c
+++ b/drivers/pinctrl/pinctrl-uclass.c
@@ -27,28 +27,6 @@
 	return flags;
 }
 
-/*
- * TODO: this function is temporary for v2019.01.
- * It should be renamed to pinctrl_decode_pin_config(),
- * the original pinctrl_decode_pin_config() function should
- * be removed and all callers of the original function should
- * be migrated to use the new one.
- */
-int pinctrl_decode_pin_config_dm(struct udevice *dev)
-{
-	int pinconfig = 0;
-
-	if (dev->uclass->uc_drv->id != UCLASS_PINCONFIG)
-		return -EINVAL;
-
-	if (dev_read_bool(dev, "bias-pull-up"))
-		pinconfig |= 1 << PIN_CONFIG_BIAS_PULL_UP;
-	else if (dev_read_bool(dev, "bias-pull-down"))
-		pinconfig |= 1 << PIN_CONFIG_BIAS_PULL_DOWN;
-
-	return pinconfig;
-}
-
 #if CONFIG_IS_ENABLED(PINCTRL_FULL)
 /**
  * pinctrl_config_one() - apply pinctrl settings for a single node
@@ -149,6 +127,9 @@
 		ofnode_get_property(node, "compatible", &ret);
 		if (ret >= 0)
 			continue;
+		/* If this node has "gpio-controller" property, skip */
+		if (ofnode_read_bool(node, "gpio-controller"))
+			continue;
 
 		if (ret != -FDT_ERR_NOTFOUND)
 			return ret;
@@ -201,11 +182,14 @@
 	int ret;
 
 	/*
-	 * For simplicity, assume the first device of PINCTRL uclass
-	 * is the correct one.  This is most likely OK as there is
-	 * usually only one pinctrl device on the system.
+	 * For most system, there is only one pincontroller device. But in
+	 * case of multiple pincontroller devices, probe the one with sequence
+	 * number 0 (defined by alias) to avoid race condition.
 	 */
-	ret = uclass_get_device(UCLASS_PINCTRL, 0, &pctldev);
+	ret = uclass_get_device_by_seq(UCLASS_PINCTRL, 0, &pctldev);
+	if (ret)
+		/* if not found, get the first one */
+		ret = uclass_get_device(UCLASS_PINCTRL, 0, &pctldev);
 	if (ret)
 		return ret;
 
diff --git a/drivers/power/pmic/Kconfig b/drivers/power/pmic/Kconfig
index 8cf60eb..b0cd260 100644
--- a/drivers/power/pmic/Kconfig
+++ b/drivers/power/pmic/Kconfig
@@ -231,10 +231,10 @@
 	DC-DC converter, 8 LDOs and a RTC. This driver binds the SMPS and LDO
 	pmic children.
 
-config PMIC_STPMU1
-	bool "Enable support for STMicroelectronics STPMU1 PMIC"
+config PMIC_STPMIC1
+	bool "Enable support for STMicroelectronics STPMIC1 PMIC"
 	depends on DM_PMIC && DM_I2C
 	---help---
-	The STPMU1 PMIC provides 4 BUCKs, 6 LDOs, 1 VREF and 2 power switches.
+	The STPMIC1 PMIC provides 4 BUCKs, 6 LDOs, 1 VREF and 2 power switches.
 	It is accessed via an I2C interface. The device is used with STM32MP1
 	SoCs. This driver implements register read/write operations.
diff --git a/drivers/power/pmic/Makefile b/drivers/power/pmic/Makefile
index 637352a..ce250cb 100644
--- a/drivers/power/pmic/Makefile
+++ b/drivers/power/pmic/Makefile
@@ -23,7 +23,7 @@
 obj-$(CONFIG_$(SPL_)PMIC_PALMAS) += palmas.o
 obj-$(CONFIG_$(SPL_)PMIC_LP873X) += lp873x.o
 obj-$(CONFIG_$(SPL_)PMIC_LP87565) += lp87565.o
-obj-$(CONFIG_PMIC_STPMU1) += stpmu1.o
+obj-$(CONFIG_PMIC_STPMIC1) += stpmic1.o
 
 obj-$(CONFIG_POWER_LTC3676) += pmic_ltc3676.o
 obj-$(CONFIG_POWER_MAX77696) += pmic_max77696.o
diff --git a/drivers/power/pmic/stpmic1.c b/drivers/power/pmic/stpmic1.c
new file mode 100644
index 0000000..65296c5
--- /dev/null
+++ b/drivers/power/pmic/stpmic1.c
@@ -0,0 +1,255 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <i2c.h>
+#include <sysreset.h>
+#include <dm/device.h>
+#include <dm/lists.h>
+#include <power/pmic.h>
+#include <power/stpmic1.h>
+
+#define STPMIC1_NUM_OF_REGS 0x100
+
+#define STPMIC1_NVM_SIZE 8
+#define STPMIC1_NVM_POLL_TIMEOUT 100000
+#define STPMIC1_NVM_START_ADDRESS 0xf8
+
+enum pmic_nvm_op {
+	SHADOW_READ,
+	SHADOW_WRITE,
+	NVM_READ,
+	NVM_WRITE,
+};
+
+#if CONFIG_IS_ENABLED(DM_REGULATOR)
+static const struct pmic_child_info stpmic1_children_info[] = {
+	{ .prefix = "ldo", .driver = "stpmic1_ldo" },
+	{ .prefix = "buck", .driver = "stpmic1_buck" },
+	{ .prefix = "vref_ddr", .driver = "stpmic1_vref_ddr" },
+	{ .prefix = "pwr_sw", .driver = "stpmic1_pwr_sw" },
+	{ .prefix = "boost", .driver = "stpmic1_boost" },
+	{ },
+};
+#endif /* DM_REGULATOR */
+
+static int stpmic1_reg_count(struct udevice *dev)
+{
+	return STPMIC1_NUM_OF_REGS;
+}
+
+static int stpmic1_write(struct udevice *dev, uint reg, const uint8_t *buff,
+			 int len)
+{
+	int ret;
+
+	ret = dm_i2c_write(dev, reg, buff, len);
+	if (ret)
+		dev_err(dev, "%s: failed to write register %#x :%d",
+			__func__, reg, ret);
+
+	return ret;
+}
+
+static int stpmic1_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
+{
+	int ret;
+
+	ret = dm_i2c_read(dev, reg, buff, len);
+	if (ret)
+		dev_err(dev, "%s: failed to read register %#x : %d",
+			__func__, reg, ret);
+
+	return ret;
+}
+
+static int stpmic1_bind(struct udevice *dev)
+{
+#if CONFIG_IS_ENABLED(DM_REGULATOR)
+	ofnode regulators_node;
+	int children;
+
+	regulators_node = dev_read_subnode(dev, "regulators");
+	if (!ofnode_valid(regulators_node)) {
+		dev_dbg(dev, "regulators subnode not found!");
+		return -ENXIO;
+	}
+	dev_dbg(dev, "found regulators subnode\n");
+
+	children = pmic_bind_children(dev, regulators_node,
+				      stpmic1_children_info);
+	if (!children)
+		dev_dbg(dev, "no child found\n");
+#endif /* DM_REGULATOR */
+
+	if (CONFIG_IS_ENABLED(SYSRESET))
+		return device_bind_driver(dev, "stpmic1-sysreset",
+					  "stpmic1-sysreset", NULL);
+
+	return 0;
+}
+
+static struct dm_pmic_ops stpmic1_ops = {
+	.reg_count = stpmic1_reg_count,
+	.read = stpmic1_read,
+	.write = stpmic1_write,
+};
+
+static const struct udevice_id stpmic1_ids[] = {
+	{ .compatible = "st,stpmic1" },
+	{ }
+};
+
+U_BOOT_DRIVER(pmic_stpmic1) = {
+	.name = "stpmic1_pmic",
+	.id = UCLASS_PMIC,
+	.of_match = stpmic1_ids,
+	.bind = stpmic1_bind,
+	.ops = &stpmic1_ops,
+};
+
+#ifndef CONFIG_SPL_BUILD
+static int stpmic1_nvm_rw(u8 addr, u8 *buf, int buf_len, enum pmic_nvm_op op)
+{
+	struct udevice *dev;
+	unsigned long timeout;
+	u8 cmd = STPMIC1_NVM_CMD_READ;
+	int ret;
+
+	ret = uclass_get_device_by_driver(UCLASS_PMIC,
+					  DM_GET_DRIVER(pmic_stpmic1), &dev);
+	if (ret)
+		/* No PMIC on power discrete board */
+		return -EOPNOTSUPP;
+
+	if (addr < STPMIC1_NVM_START_ADDRESS)
+		return -EACCES;
+
+	if (op == SHADOW_READ)
+		return pmic_read(dev, addr, buf, buf_len);
+
+	if (op == SHADOW_WRITE)
+		return pmic_write(dev, addr, buf, buf_len);
+
+	if (op == NVM_WRITE) {
+		cmd = STPMIC1_NVM_CMD_PROGRAM;
+
+		ret = pmic_write(dev, addr, buf, buf_len);
+		if (ret < 0)
+			return ret;
+	}
+
+	ret = pmic_reg_read(dev, STPMIC1_NVM_CR);
+	if (ret < 0)
+		return ret;
+
+	ret = pmic_reg_write(dev, STPMIC1_NVM_CR, ret | cmd);
+	if (ret < 0)
+		return ret;
+
+	timeout = timer_get_us() + STPMIC1_NVM_POLL_TIMEOUT;
+	for (;;) {
+		ret = pmic_reg_read(dev, STPMIC1_NVM_SR);
+		if (ret < 0)
+			return ret;
+
+		if (!(ret & STPMIC1_NVM_BUSY))
+			break;
+
+		if (time_after(timer_get_us(), timeout))
+			break;
+	}
+
+	if (ret & STPMIC1_NVM_BUSY)
+		return -ETIMEDOUT;
+
+	if (op == NVM_READ) {
+		ret = pmic_read(dev, addr, buf, buf_len);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+
+int stpmic1_shadow_read_byte(u8 addr, u8 *buf)
+{
+	return stpmic1_nvm_rw(addr, buf, 1, SHADOW_READ);
+}
+
+int stpmic1_shadow_write_byte(u8 addr, u8 *buf)
+{
+	return stpmic1_nvm_rw(addr, buf, 1, SHADOW_WRITE);
+}
+
+int stpmic1_nvm_read_byte(u8 addr, u8 *buf)
+{
+	return stpmic1_nvm_rw(addr, buf, 1, NVM_READ);
+}
+
+int stpmic1_nvm_write_byte(u8 addr, u8 *buf)
+{
+	return stpmic1_nvm_rw(addr, buf, 1, NVM_WRITE);
+}
+
+int stpmic1_nvm_read_all(u8 *buf, int buf_len)
+{
+	if (buf_len != STPMIC1_NVM_SIZE)
+		return -EINVAL;
+
+	return stpmic1_nvm_rw(STPMIC1_NVM_START_ADDRESS,
+			     buf, buf_len, NVM_READ);
+}
+
+int stpmic1_nvm_write_all(u8 *buf, int buf_len)
+{
+	if (buf_len != STPMIC1_NVM_SIZE)
+		return -EINVAL;
+
+	return stpmic1_nvm_rw(STPMIC1_NVM_START_ADDRESS,
+			     buf, buf_len, NVM_WRITE);
+}
+#endif /* CONFIG_SPL_BUILD */
+
+#ifdef CONFIG_SYSRESET
+static int stpmic1_sysreset_request(struct udevice *dev, enum sysreset_t type)
+{
+	struct udevice *pmic_dev;
+	int ret;
+
+	if (type != SYSRESET_POWER)
+		return -EPROTONOSUPPORT;
+
+	ret = uclass_get_device_by_driver(UCLASS_PMIC,
+					  DM_GET_DRIVER(pmic_stpmic1),
+					  &pmic_dev);
+
+	if (ret)
+		return -EOPNOTSUPP;
+
+	ret = pmic_reg_read(pmic_dev, STPMIC1_MAIN_CR);
+	if (ret < 0)
+		return ret;
+
+	ret = pmic_reg_write(pmic_dev, STPMIC1_MAIN_CR,
+			     ret | STPMIC1_SWOFF | STPMIC1_RREQ_EN);
+	if (ret < 0)
+		return ret;
+
+	return -EINPROGRESS;
+}
+
+static struct sysreset_ops stpmic1_sysreset_ops = {
+	.request = stpmic1_sysreset_request,
+};
+
+U_BOOT_DRIVER(stpmic1_sysreset) = {
+	.name = "stpmic1-sysreset",
+	.id = UCLASS_SYSRESET,
+	.ops = &stpmic1_sysreset_ops,
+};
+#endif
diff --git a/drivers/power/pmic/stpmu1.c b/drivers/power/pmic/stpmu1.c
deleted file mode 100644
index 47af012..0000000
--- a/drivers/power/pmic/stpmu1.c
+++ /dev/null
@@ -1,95 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
-/*
- * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
- */
-
-#include <common.h>
-#include <dm.h>
-#include <errno.h>
-#include <i2c.h>
-#include <power/pmic.h>
-#include <power/stpmu1.h>
-
-#define STMPU1_NUM_OF_REGS 0x100
-
-#ifndef CONFIG_SPL_BUILD
-static const struct pmic_child_info stpmu1_children_info[] = {
-	{ .prefix = "ldo", .driver = "stpmu1_ldo" },
-	{ .prefix = "buck", .driver = "stpmu1_buck" },
-	{ .prefix = "vref_ddr", .driver = "stpmu1_vref_ddr" },
-	{ .prefix = "pwr_sw", .driver = "stpmu1_pwr_sw" },
-	{ .prefix = "boost", .driver = "stpmu1_boost" },
-	{ },
-};
-#endif /* CONFIG_SPL_BUILD */
-
-static int stpmu1_reg_count(struct udevice *dev)
-{
-	return STMPU1_NUM_OF_REGS;
-}
-
-static int stpmu1_write(struct udevice *dev, uint reg, const uint8_t *buff,
-			int len)
-{
-	int ret;
-
-	ret = dm_i2c_write(dev, reg, buff, len);
-	if (ret)
-		dev_err(dev, "%s: failed to write register %#x :%d",
-			__func__, reg, ret);
-
-	return ret;
-}
-
-static int stpmu1_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
-{
-	int ret;
-
-	ret = dm_i2c_read(dev, reg, buff, len);
-	if (ret)
-		dev_err(dev, "%s: failed to read register %#x : %d",
-			__func__, reg, ret);
-
-	return ret;
-}
-
-static int stpmu1_bind(struct udevice *dev)
-{
-#ifndef CONFIG_SPL_BUILD
-	ofnode regulators_node;
-	int children;
-
-	regulators_node = dev_read_subnode(dev, "regulators");
-	if (!ofnode_valid(regulators_node)) {
-		dev_dbg(dev, "regulators subnode not found!\n");
-		return -ENXIO;
-	}
-	dev_dbg(dev, "found regulators subnode\n");
-
-	children = pmic_bind_children(dev, regulators_node,
-				      stpmu1_children_info);
-	if (!children)
-		dev_dbg(dev, "no child found\n");
-#endif /* CONFIG_SPL_BUILD */
-
-	return 0;
-}
-
-static struct dm_pmic_ops stpmu1_ops = {
-	.reg_count = stpmu1_reg_count,
-	.read = stpmu1_read,
-	.write = stpmu1_write,
-};
-
-static const struct udevice_id stpmu1_ids[] = {
-	{ .compatible = "st,stpmu1" },
-	{ }
-};
-
-U_BOOT_DRIVER(pmic_stpmu1) = {
-	.name = "stpmu1_pmic",
-	.id = UCLASS_PMIC,
-	.of_match = stpmu1_ids,
-	.bind = stpmu1_bind,
-	.ops = &stpmu1_ops,
-};
diff --git a/drivers/power/regulator/Kconfig b/drivers/power/regulator/Kconfig
index 3ed0dd2..72dfc48 100644
--- a/drivers/power/regulator/Kconfig
+++ b/drivers/power/regulator/Kconfig
@@ -244,11 +244,17 @@
 	regulator types of the TPS65910 (BUCK, BOOST and LDO). It implements
 	the get/set api for value and enable.
 
-config DM_REGULATOR_STPMU1
-	bool "Enable driver for STPMU1 regulators"
-	depends on DM_REGULATOR && PMIC_STPMU1
+config DM_REGULATOR_STPMIC1
+	bool "Enable driver for STPMIC1 regulators"
+	depends on DM_REGULATOR && PMIC_STPMIC1
 	---help---
-	Enable support for the regulator functions of the STPMU1 PMIC. The
+	Enable support for the regulator functions of the STPMIC1 PMIC. The
 	driver implements get/set api for the various BUCKS and LDOs supported
 	by the PMIC device. This driver is controlled by a device tree node
 	which includes voltage limits.
+
+config SPL_DM_REGULATOR_STPMIC1
+	bool "Enable driver for STPMIC1 regulators in SPL"
+	depends on SPL_DM_REGULATOR && PMIC_STPMIC1
+	help
+	  Enable support for the regulator functions of the STPMIC1 PMIC in SPL.
diff --git a/drivers/power/regulator/Makefile b/drivers/power/regulator/Makefile
index f617ce7..8c1506c 100644
--- a/drivers/power/regulator/Makefile
+++ b/drivers/power/regulator/Makefile
@@ -24,4 +24,4 @@
 obj-$(CONFIG_$(SPL_)DM_REGULATOR_LP87565) += lp87565_regulator.o
 obj-$(CONFIG_$(SPL_)DM_REGULATOR_STM32_VREFBUF) += stm32-vrefbuf.o
 obj-$(CONFIG_DM_REGULATOR_TPS65910) += tps65910_regulator.o
-obj-$(CONFIG_$(SPL_)DM_REGULATOR_STPMU1) += stpmu1.o
+obj-$(CONFIG_$(SPL_)DM_REGULATOR_STPMIC1) += stpmic1.o
diff --git a/drivers/power/regulator/stpmic1.c b/drivers/power/regulator/stpmic1.c
new file mode 100644
index 0000000..50ef2a2
--- /dev/null
+++ b/drivers/power/regulator/stpmic1.c
@@ -0,0 +1,672 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+ * Author: Christophe Kerello <christophe.kerello@st.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <power/pmic.h>
+#include <power/regulator.h>
+#include <power/stpmic1.h>
+
+struct stpmic1_range {
+	int min_uv;
+	int min_sel;
+	int max_sel;
+	int step;
+};
+
+struct stpmic1_output {
+	const struct stpmic1_range *ranges;
+	int nbranges;
+};
+
+#define STPMIC1_MODE(_id, _val, _name) { \
+	.id = _id,			\
+	.register_value = _val,		\
+	.name = _name,			\
+}
+
+#define STPMIC1_RANGE(_min_uv, _min_sel, _max_sel, _step) { \
+	.min_uv = _min_uv,		\
+	.min_sel = _min_sel,		\
+	.max_sel = _max_sel,		\
+	.step = _step,			\
+}
+
+#define STPMIC1_OUTPUT(_ranges, _nbranges) { \
+	.ranges = _ranges,		\
+	.nbranges = _nbranges,		\
+}
+
+static int stpmic1_output_find_uv(int sel,
+				  const struct stpmic1_output *output)
+{
+	const struct stpmic1_range *range;
+	int i;
+
+	for (i = 0, range = output->ranges;
+	     i < output->nbranges; i++, range++) {
+		if (sel >= range->min_sel && sel <= range->max_sel)
+			return range->min_uv +
+			       (sel - range->min_sel) * range->step;
+	}
+
+	return -EINVAL;
+}
+
+static int stpmic1_output_find_sel(int uv,
+				   const struct stpmic1_output *output)
+{
+	const struct stpmic1_range *range;
+	int i;
+
+	for (i = 0, range = output->ranges;
+	     i < output->nbranges; i++, range++) {
+		if (uv == range->min_uv && !range->step)
+			return range->min_sel;
+
+		if (uv >= range->min_uv &&
+		    uv <= range->min_uv +
+			  (range->max_sel - range->min_sel) * range->step)
+			return range->min_sel +
+			       (uv - range->min_uv) / range->step;
+	}
+
+	return -EINVAL;
+}
+
+/*
+ * BUCK regulators
+ */
+
+static const struct stpmic1_range buck1_ranges[] = {
+	STPMIC1_RANGE(725000, 0, 4, 0),
+	STPMIC1_RANGE(725000, 5, 36, 25000),
+	STPMIC1_RANGE(1500000, 37, 63, 0),
+};
+
+static const struct stpmic1_range buck2_ranges[] = {
+	STPMIC1_RANGE(1000000, 0, 17, 0),
+	STPMIC1_RANGE(1050000, 18, 19, 0),
+	STPMIC1_RANGE(1100000, 20, 21, 0),
+	STPMIC1_RANGE(1150000, 22, 23, 0),
+	STPMIC1_RANGE(1200000, 24, 25, 0),
+	STPMIC1_RANGE(1250000, 26, 27, 0),
+	STPMIC1_RANGE(1300000, 28, 29, 0),
+	STPMIC1_RANGE(1350000, 30, 31, 0),
+	STPMIC1_RANGE(1400000, 32, 33, 0),
+	STPMIC1_RANGE(1450000, 34, 35, 0),
+	STPMIC1_RANGE(1500000, 36, 63, 0),
+};
+
+static const struct stpmic1_range buck3_ranges[] = {
+	STPMIC1_RANGE(1000000, 0, 19, 0),
+	STPMIC1_RANGE(1100000, 20, 23, 0),
+	STPMIC1_RANGE(1200000, 24, 27, 0),
+	STPMIC1_RANGE(1300000, 28, 31, 0),
+	STPMIC1_RANGE(1400000, 32, 35, 0),
+	STPMIC1_RANGE(1500000, 36, 55, 100000),
+	STPMIC1_RANGE(3400000, 56, 63, 0),
+};
+
+static const struct stpmic1_range buck4_ranges[] = {
+	STPMIC1_RANGE(600000, 0, 27, 25000),
+	STPMIC1_RANGE(1300000, 28, 29, 0),
+	STPMIC1_RANGE(1350000, 30, 31, 0),
+	STPMIC1_RANGE(1400000, 32, 33, 0),
+	STPMIC1_RANGE(1450000, 34, 35, 0),
+	STPMIC1_RANGE(1500000, 36, 60, 100000),
+	STPMIC1_RANGE(3900000, 61, 63, 0),
+};
+
+/* BUCK: 1,2,3,4 - voltage ranges */
+static const struct stpmic1_output buck_voltage_range[] = {
+	STPMIC1_OUTPUT(buck1_ranges, ARRAY_SIZE(buck1_ranges)),
+	STPMIC1_OUTPUT(buck2_ranges, ARRAY_SIZE(buck2_ranges)),
+	STPMIC1_OUTPUT(buck3_ranges, ARRAY_SIZE(buck3_ranges)),
+	STPMIC1_OUTPUT(buck4_ranges, ARRAY_SIZE(buck4_ranges)),
+};
+
+/* BUCK modes */
+static const struct dm_regulator_mode buck_modes[] = {
+	STPMIC1_MODE(STPMIC1_PREG_MODE_HP, STPMIC1_PREG_MODE_HP, "HP"),
+	STPMIC1_MODE(STPMIC1_PREG_MODE_LP, STPMIC1_PREG_MODE_LP, "LP"),
+};
+
+static int stpmic1_buck_get_uv(struct udevice *dev, int buck)
+{
+	int sel;
+
+	sel = pmic_reg_read(dev, STPMIC1_BUCKX_MAIN_CR(buck));
+	if (sel < 0)
+		return sel;
+
+	sel &= STPMIC1_BUCK_VOUT_MASK;
+	sel >>= STPMIC1_BUCK_VOUT_SHIFT;
+
+	return stpmic1_output_find_uv(sel, &buck_voltage_range[buck]);
+}
+
+static int stpmic1_buck_get_value(struct udevice *dev)
+{
+	return stpmic1_buck_get_uv(dev->parent, dev->driver_data - 1);
+}
+
+static int stpmic1_buck_set_value(struct udevice *dev, int uv)
+{
+	int sel, buck = dev->driver_data - 1;
+
+	sel = stpmic1_output_find_sel(uv, &buck_voltage_range[buck]);
+	if (sel < 0)
+		return sel;
+
+	return pmic_clrsetbits(dev->parent,
+			       STPMIC1_BUCKX_MAIN_CR(buck),
+			       STPMIC1_BUCK_VOUT_MASK,
+			       sel << STPMIC1_BUCK_VOUT_SHIFT);
+}
+
+static int stpmic1_buck_get_enable(struct udevice *dev)
+{
+	int ret;
+
+	ret = pmic_reg_read(dev->parent,
+			    STPMIC1_BUCKX_MAIN_CR(dev->driver_data - 1));
+	if (ret < 0)
+		return false;
+
+	return ret & STPMIC1_BUCK_ENA ? true : false;
+}
+
+static int stpmic1_buck_set_enable(struct udevice *dev, bool enable)
+{
+	struct dm_regulator_uclass_platdata *uc_pdata;
+	int delay = enable ? STPMIC1_DEFAULT_START_UP_DELAY_MS :
+			     STPMIC1_DEFAULT_STOP_DELAY_MS;
+	int ret, uv;
+
+	/* if regulator is already in the wanted state, nothing to do */
+	if (stpmic1_buck_get_enable(dev) == enable)
+		return 0;
+
+	if (enable) {
+		uc_pdata = dev_get_uclass_platdata(dev);
+		uv = stpmic1_buck_get_value(dev);
+		if (uv < uc_pdata->min_uV || uv > uc_pdata->max_uV)
+			stpmic1_buck_set_value(dev, uc_pdata->min_uV);
+	}
+
+	ret = pmic_clrsetbits(dev->parent,
+			      STPMIC1_BUCKX_MAIN_CR(dev->driver_data - 1),
+			      STPMIC1_BUCK_ENA, enable ? STPMIC1_BUCK_ENA : 0);
+	mdelay(delay);
+
+	return ret;
+}
+
+static int stpmic1_buck_get_mode(struct udevice *dev)
+{
+	int ret;
+
+	ret = pmic_reg_read(dev->parent,
+			    STPMIC1_BUCKX_MAIN_CR(dev->driver_data - 1));
+	if (ret < 0)
+		return ret;
+
+	return ret & STPMIC1_BUCK_PREG_MODE ? STPMIC1_PREG_MODE_LP :
+					      STPMIC1_PREG_MODE_HP;
+}
+
+static int stpmic1_buck_set_mode(struct udevice *dev, int mode)
+{
+	return pmic_clrsetbits(dev->parent,
+			       STPMIC1_BUCKX_MAIN_CR(dev->driver_data - 1),
+			       STPMIC1_BUCK_PREG_MODE,
+			       mode ? STPMIC1_BUCK_PREG_MODE : 0);
+}
+
+static int stpmic1_buck_probe(struct udevice *dev)
+{
+	struct dm_regulator_uclass_platdata *uc_pdata;
+
+	if (!dev->driver_data || dev->driver_data > STPMIC1_MAX_BUCK)
+		return -EINVAL;
+
+	uc_pdata = dev_get_uclass_platdata(dev);
+
+	uc_pdata->type = REGULATOR_TYPE_BUCK;
+	uc_pdata->mode = (struct dm_regulator_mode *)buck_modes;
+	uc_pdata->mode_count = ARRAY_SIZE(buck_modes);
+
+	return 0;
+}
+
+static const struct dm_regulator_ops stpmic1_buck_ops = {
+	.get_value  = stpmic1_buck_get_value,
+	.set_value  = stpmic1_buck_set_value,
+	.get_enable = stpmic1_buck_get_enable,
+	.set_enable = stpmic1_buck_set_enable,
+	.get_mode   = stpmic1_buck_get_mode,
+	.set_mode   = stpmic1_buck_set_mode,
+};
+
+U_BOOT_DRIVER(stpmic1_buck) = {
+	.name = "stpmic1_buck",
+	.id = UCLASS_REGULATOR,
+	.ops = &stpmic1_buck_ops,
+	.probe = stpmic1_buck_probe,
+};
+
+/*
+ * LDO regulators
+ */
+
+static const struct stpmic1_range ldo12_ranges[] = {
+	STPMIC1_RANGE(1700000, 0, 7, 0),
+	STPMIC1_RANGE(1700000, 8, 24, 100000),
+	STPMIC1_RANGE(3300000, 25, 31, 0),
+};
+
+static const struct stpmic1_range ldo3_ranges[] = {
+	STPMIC1_RANGE(1700000, 0, 7, 0),
+	STPMIC1_RANGE(1700000, 8, 24, 100000),
+	STPMIC1_RANGE(3300000, 25, 30, 0),
+	/* Sel 31 is special case when LDO3 is in mode sync_source (BUCK2/2) */
+};
+
+static const struct stpmic1_range ldo5_ranges[] = {
+	STPMIC1_RANGE(1700000, 0, 7, 0),
+	STPMIC1_RANGE(1700000, 8, 30, 100000),
+	STPMIC1_RANGE(3900000, 31, 31, 0),
+};
+
+static const struct stpmic1_range ldo6_ranges[] = {
+	STPMIC1_RANGE(900000, 0, 24, 100000),
+	STPMIC1_RANGE(3300000, 25, 31, 0),
+};
+
+/* LDO: 1,2,3,4,5,6 - voltage ranges */
+static const struct stpmic1_output ldo_voltage_range[] = {
+	STPMIC1_OUTPUT(ldo12_ranges, ARRAY_SIZE(ldo12_ranges)),
+	STPMIC1_OUTPUT(ldo12_ranges, ARRAY_SIZE(ldo12_ranges)),
+	STPMIC1_OUTPUT(ldo3_ranges, ARRAY_SIZE(ldo3_ranges)),
+	STPMIC1_OUTPUT(NULL, 0),
+	STPMIC1_OUTPUT(ldo5_ranges, ARRAY_SIZE(ldo5_ranges)),
+	STPMIC1_OUTPUT(ldo6_ranges, ARRAY_SIZE(ldo6_ranges)),
+};
+
+/* LDO modes */
+static const struct dm_regulator_mode ldo_modes[] = {
+	STPMIC1_MODE(STPMIC1_LDO_MODE_NORMAL,
+		     STPMIC1_LDO_MODE_NORMAL, "NORMAL"),
+	STPMIC1_MODE(STPMIC1_LDO_MODE_BYPASS,
+		     STPMIC1_LDO_MODE_BYPASS, "BYPASS"),
+	STPMIC1_MODE(STPMIC1_LDO_MODE_SINK_SOURCE,
+		     STPMIC1_LDO_MODE_SINK_SOURCE, "SINK SOURCE"),
+};
+
+static int stpmic1_ldo_get_value(struct udevice *dev)
+{
+	int sel, ldo = dev->driver_data - 1;
+
+	sel = pmic_reg_read(dev->parent, STPMIC1_LDOX_MAIN_CR(ldo));
+	if (sel < 0)
+		return sel;
+
+	/* ldo4 => 3,3V */
+	if (ldo == STPMIC1_LDO4)
+		return STPMIC1_LDO4_UV;
+
+	sel &= STPMIC1_LDO12356_VOUT_MASK;
+	sel >>= STPMIC1_LDO12356_VOUT_SHIFT;
+
+	/* ldo3, sel = 31 => BUCK2/2 */
+	if (ldo == STPMIC1_LDO3 && sel == STPMIC1_LDO3_DDR_SEL)
+		return stpmic1_buck_get_uv(dev->parent, STPMIC1_BUCK2) / 2;
+
+	return stpmic1_output_find_uv(sel, &ldo_voltage_range[ldo]);
+}
+
+static int stpmic1_ldo_set_value(struct udevice *dev, int uv)
+{
+	int sel, ldo = dev->driver_data - 1;
+
+	/* ldo4 => not possible */
+	if (ldo == STPMIC1_LDO4)
+		return -EINVAL;
+
+	sel = stpmic1_output_find_sel(uv, &ldo_voltage_range[ldo]);
+	if (sel < 0)
+		return sel;
+
+	return pmic_clrsetbits(dev->parent,
+			       STPMIC1_LDOX_MAIN_CR(ldo),
+			       STPMIC1_LDO12356_VOUT_MASK,
+			       sel << STPMIC1_LDO12356_VOUT_SHIFT);
+}
+
+static int stpmic1_ldo_get_enable(struct udevice *dev)
+{
+	int ret;
+
+	ret = pmic_reg_read(dev->parent,
+			    STPMIC1_LDOX_MAIN_CR(dev->driver_data - 1));
+	if (ret < 0)
+		return false;
+
+	return ret & STPMIC1_LDO_ENA ? true : false;
+}
+
+static int stpmic1_ldo_set_enable(struct udevice *dev, bool enable)
+{
+	struct dm_regulator_uclass_platdata *uc_pdata;
+	int delay = enable ? STPMIC1_DEFAULT_START_UP_DELAY_MS :
+			     STPMIC1_DEFAULT_STOP_DELAY_MS;
+	int ret, uv;
+
+	/* if regulator is already in the wanted state, nothing to do */
+	if (stpmic1_ldo_get_enable(dev) == enable)
+		return 0;
+
+	if (enable) {
+		uc_pdata = dev_get_uclass_platdata(dev);
+		uv = stpmic1_ldo_get_value(dev);
+		if (uv < uc_pdata->min_uV || uv > uc_pdata->max_uV)
+			stpmic1_ldo_set_value(dev, uc_pdata->min_uV);
+	}
+
+	ret = pmic_clrsetbits(dev->parent,
+			      STPMIC1_LDOX_MAIN_CR(dev->driver_data - 1),
+			      STPMIC1_LDO_ENA, enable ? STPMIC1_LDO_ENA : 0);
+	mdelay(delay);
+
+	return ret;
+}
+
+static int stpmic1_ldo_get_mode(struct udevice *dev)
+{
+	int ret, ldo = dev->driver_data - 1;
+
+	if (ldo != STPMIC1_LDO3)
+		return -EINVAL;
+
+	ret = pmic_reg_read(dev->parent, STPMIC1_LDOX_MAIN_CR(ldo));
+	if (ret < 0)
+		return ret;
+
+	if (ret & STPMIC1_LDO3_MODE)
+		return STPMIC1_LDO_MODE_BYPASS;
+
+	ret &= STPMIC1_LDO12356_VOUT_MASK;
+	ret >>= STPMIC1_LDO12356_VOUT_SHIFT;
+
+	return ret == STPMIC1_LDO3_DDR_SEL ? STPMIC1_LDO_MODE_SINK_SOURCE :
+					     STPMIC1_LDO_MODE_NORMAL;
+}
+
+static int stpmic1_ldo_set_mode(struct udevice *dev, int mode)
+{
+	int ret, ldo = dev->driver_data - 1;
+
+	if (ldo != STPMIC1_LDO3)
+		return -EINVAL;
+
+	ret = pmic_reg_read(dev->parent, STPMIC1_LDOX_MAIN_CR(ldo));
+	if (ret < 0)
+		return ret;
+
+	switch (mode) {
+	case STPMIC1_LDO_MODE_SINK_SOURCE:
+		ret &= ~STPMIC1_LDO12356_VOUT_MASK;
+		ret |= STPMIC1_LDO3_DDR_SEL << STPMIC1_LDO12356_VOUT_SHIFT;
+	case STPMIC1_LDO_MODE_NORMAL:
+		ret &= ~STPMIC1_LDO3_MODE;
+		break;
+	case STPMIC1_LDO_MODE_BYPASS:
+		ret |= STPMIC1_LDO3_MODE;
+		break;
+	}
+
+	return pmic_reg_write(dev->parent, STPMIC1_LDOX_MAIN_CR(ldo), ret);
+}
+
+static int stpmic1_ldo_probe(struct udevice *dev)
+{
+	struct dm_regulator_uclass_platdata *uc_pdata;
+
+	if (!dev->driver_data || dev->driver_data > STPMIC1_MAX_LDO)
+		return -EINVAL;
+
+	uc_pdata = dev_get_uclass_platdata(dev);
+
+	uc_pdata->type = REGULATOR_TYPE_LDO;
+	if (dev->driver_data - 1 == STPMIC1_LDO3) {
+		uc_pdata->mode = (struct dm_regulator_mode *)ldo_modes;
+		uc_pdata->mode_count = ARRAY_SIZE(ldo_modes);
+	} else {
+		uc_pdata->mode_count = 0;
+	}
+
+	return 0;
+}
+
+static const struct dm_regulator_ops stpmic1_ldo_ops = {
+	.get_value  = stpmic1_ldo_get_value,
+	.set_value  = stpmic1_ldo_set_value,
+	.get_enable = stpmic1_ldo_get_enable,
+	.set_enable = stpmic1_ldo_set_enable,
+	.get_mode   = stpmic1_ldo_get_mode,
+	.set_mode   = stpmic1_ldo_set_mode,
+};
+
+U_BOOT_DRIVER(stpmic1_ldo) = {
+	.name = "stpmic1_ldo",
+	.id = UCLASS_REGULATOR,
+	.ops = &stpmic1_ldo_ops,
+	.probe = stpmic1_ldo_probe,
+};
+
+/*
+ * VREF DDR regulator
+ */
+
+static int stpmic1_vref_ddr_get_value(struct udevice *dev)
+{
+	/* BUCK2/2 */
+	return stpmic1_buck_get_uv(dev->parent, STPMIC1_BUCK2) / 2;
+}
+
+static int stpmic1_vref_ddr_get_enable(struct udevice *dev)
+{
+	int ret;
+
+	ret = pmic_reg_read(dev->parent, STPMIC1_REFDDR_MAIN_CR);
+	if (ret < 0)
+		return false;
+
+	return ret & STPMIC1_VREF_ENA ? true : false;
+}
+
+static int stpmic1_vref_ddr_set_enable(struct udevice *dev, bool enable)
+{
+	int delay = enable ? STPMIC1_DEFAULT_START_UP_DELAY_MS :
+			     STPMIC1_DEFAULT_STOP_DELAY_MS;
+	int ret;
+
+	/* if regulator is already in the wanted state, nothing to do */
+	if (stpmic1_vref_ddr_get_enable(dev) == enable)
+		return 0;
+
+	ret = pmic_clrsetbits(dev->parent, STPMIC1_REFDDR_MAIN_CR,
+			      STPMIC1_VREF_ENA, enable ? STPMIC1_VREF_ENA : 0);
+	mdelay(delay);
+
+	return ret;
+}
+
+static int stpmic1_vref_ddr_probe(struct udevice *dev)
+{
+	struct dm_regulator_uclass_platdata *uc_pdata;
+
+	uc_pdata = dev_get_uclass_platdata(dev);
+
+	uc_pdata->type = REGULATOR_TYPE_FIXED;
+	uc_pdata->mode_count = 0;
+
+	return 0;
+}
+
+static const struct dm_regulator_ops stpmic1_vref_ddr_ops = {
+	.get_value  = stpmic1_vref_ddr_get_value,
+	.get_enable = stpmic1_vref_ddr_get_enable,
+	.set_enable = stpmic1_vref_ddr_set_enable,
+};
+
+U_BOOT_DRIVER(stpmic1_vref_ddr) = {
+	.name = "stpmic1_vref_ddr",
+	.id = UCLASS_REGULATOR,
+	.ops = &stpmic1_vref_ddr_ops,
+	.probe = stpmic1_vref_ddr_probe,
+};
+
+/*
+ * BOOST regulator
+ */
+
+static int stpmic1_boost_get_enable(struct udevice *dev)
+{
+	int ret;
+
+	ret = pmic_reg_read(dev->parent, STPMIC1_BST_SW_CR);
+	if (ret < 0)
+		return false;
+
+	return ret & STPMIC1_BST_ON ? true : false;
+}
+
+static int stpmic1_boost_set_enable(struct udevice *dev, bool enable)
+{
+	int ret;
+
+	ret = pmic_reg_read(dev->parent, STPMIC1_BST_SW_CR);
+	if (ret < 0)
+		return ret;
+
+	if (!enable && ret & STPMIC1_PWR_SW_ON)
+		return -EINVAL;
+
+	/* if regulator is already in the wanted state, nothing to do */
+	if (!!(ret & STPMIC1_BST_ON) == enable)
+		return 0;
+
+	ret = pmic_clrsetbits(dev->parent, STPMIC1_BST_SW_CR,
+			      STPMIC1_BST_ON,
+			      enable ? STPMIC1_BST_ON : 0);
+	if (enable)
+		mdelay(STPMIC1_USB_BOOST_START_UP_DELAY_MS);
+
+	return ret;
+}
+
+static int stpmic1_boost_probe(struct udevice *dev)
+{
+	struct dm_regulator_uclass_platdata *uc_pdata;
+
+	uc_pdata = dev_get_uclass_platdata(dev);
+
+	uc_pdata->type = REGULATOR_TYPE_FIXED;
+	uc_pdata->mode_count = 0;
+
+	return 0;
+}
+
+static const struct dm_regulator_ops stpmic1_boost_ops = {
+	.get_enable = stpmic1_boost_get_enable,
+	.set_enable = stpmic1_boost_set_enable,
+};
+
+U_BOOT_DRIVER(stpmic1_boost) = {
+	.name = "stpmic1_boost",
+	.id = UCLASS_REGULATOR,
+	.ops = &stpmic1_boost_ops,
+	.probe = stpmic1_boost_probe,
+};
+
+/*
+ * USB power switch
+ */
+
+static int stpmic1_pwr_sw_get_enable(struct udevice *dev)
+{
+	uint mask = 1 << dev->driver_data;
+	int ret;
+
+	ret = pmic_reg_read(dev->parent, STPMIC1_BST_SW_CR);
+	if (ret < 0)
+		return false;
+
+	return ret & mask ? true : false;
+}
+
+static int stpmic1_pwr_sw_set_enable(struct udevice *dev, bool enable)
+{
+	uint mask = 1 << dev->driver_data;
+	int delay = enable ? STPMIC1_DEFAULT_START_UP_DELAY_MS :
+			     STPMIC1_DEFAULT_STOP_DELAY_MS;
+	int ret;
+
+	ret = pmic_reg_read(dev->parent, STPMIC1_BST_SW_CR);
+	if (ret < 0)
+		return ret;
+
+	/* if regulator is already in the wanted state, nothing to do */
+	if (!!(ret & mask) == enable)
+		return 0;
+
+	/* Boost management */
+	if (enable && !(ret & STPMIC1_BST_ON)) {
+		pmic_clrsetbits(dev->parent, STPMIC1_BST_SW_CR,
+				STPMIC1_BST_ON, STPMIC1_BST_ON);
+		mdelay(STPMIC1_USB_BOOST_START_UP_DELAY_MS);
+	} else if (!enable && ret & STPMIC1_BST_ON &&
+		   (ret & STPMIC1_PWR_SW_ON) != STPMIC1_PWR_SW_ON) {
+		pmic_clrsetbits(dev->parent, STPMIC1_BST_SW_CR,
+				STPMIC1_BST_ON, 0);
+	}
+
+	ret = pmic_clrsetbits(dev->parent, STPMIC1_BST_SW_CR,
+			      mask, enable ? mask : 0);
+	mdelay(delay);
+
+	return ret;
+}
+
+static int stpmic1_pwr_sw_probe(struct udevice *dev)
+{
+	struct dm_regulator_uclass_platdata *uc_pdata;
+
+	if (!dev->driver_data || dev->driver_data > STPMIC1_MAX_PWR_SW)
+		return -EINVAL;
+
+	uc_pdata = dev_get_uclass_platdata(dev);
+
+	uc_pdata->type = REGULATOR_TYPE_FIXED;
+	uc_pdata->mode_count = 0;
+
+	return 0;
+}
+
+static const struct dm_regulator_ops stpmic1_pwr_sw_ops = {
+	.get_enable = stpmic1_pwr_sw_get_enable,
+	.set_enable = stpmic1_pwr_sw_set_enable,
+};
+
+U_BOOT_DRIVER(stpmic1_pwr_sw) = {
+	.name = "stpmic1_pwr_sw",
+	.id = UCLASS_REGULATOR,
+	.ops = &stpmic1_pwr_sw_ops,
+	.probe = stpmic1_pwr_sw_probe,
+};
diff --git a/drivers/power/regulator/stpmu1.c b/drivers/power/regulator/stpmu1.c
deleted file mode 100644
index 6eb2420..0000000
--- a/drivers/power/regulator/stpmu1.c
+++ /dev/null
@@ -1,671 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
-/*
- * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
- * Author: Christophe Kerello <christophe.kerello@st.com>
- */
-
-#include <common.h>
-#include <dm.h>
-#include <errno.h>
-#include <power/pmic.h>
-#include <power/regulator.h>
-#include <power/stpmu1.h>
-
-struct stpmu1_range {
-	int min_uv;
-	int min_sel;
-	int max_sel;
-	int step;
-};
-
-struct stpmu1_output_range {
-	const struct stpmu1_range *ranges;
-	int nbranges;
-};
-
-#define STPMU1_MODE(_id, _val, _name) { \
-	.id = _id,			\
-	.register_value = _val,		\
-	.name = _name,			\
-}
-
-#define STPMU1_RANGE(_min_uv, _min_sel, _max_sel, _step) { \
-	.min_uv = _min_uv,		\
-	.min_sel = _min_sel,		\
-	.max_sel = _max_sel,		\
-	.step = _step,			\
-}
-
-#define STPMU1_OUTPUT_RANGE(_ranges, _nbranges) { \
-	.ranges = _ranges,		\
-	.nbranges = _nbranges,		\
-}
-
-static int stpmu1_output_find_uv(int sel,
-				 const struct stpmu1_output_range *output_range)
-{
-	const struct stpmu1_range *range;
-	int i;
-
-	for (i = 0, range = output_range->ranges;
-	     i < output_range->nbranges; i++, range++) {
-		if (sel >= range->min_sel && sel <= range->max_sel)
-			return range->min_uv +
-			       (sel - range->min_sel) * range->step;
-	}
-
-	return -EINVAL;
-}
-
-static int stpmu1_output_find_sel(int uv,
-				  const struct stpmu1_output_range *output_range)
-{
-	const struct stpmu1_range *range;
-	int i;
-
-	for (i = 0, range = output_range->ranges;
-	     i < output_range->nbranges; i++, range++) {
-		if (uv == range->min_uv && !range->step)
-			return range->min_sel;
-
-		if (uv >= range->min_uv &&
-		    uv <= range->min_uv +
-			  (range->max_sel - range->min_sel) * range->step)
-			return range->min_sel +
-			       (uv - range->min_uv) / range->step;
-	}
-
-	return -EINVAL;
-}
-
-/*
- * BUCK regulators
- */
-
-static const struct stpmu1_range buck1_ranges[] = {
-	STPMU1_RANGE(600000, 0, 30, 25000),
-	STPMU1_RANGE(1350000, 31, 63, 0),
-};
-
-static const struct stpmu1_range buck2_ranges[] = {
-	STPMU1_RANGE(1000000, 0, 17, 0),
-	STPMU1_RANGE(1050000, 18, 19, 0),
-	STPMU1_RANGE(1100000, 20, 21, 0),
-	STPMU1_RANGE(1150000, 22, 23, 0),
-	STPMU1_RANGE(1200000, 24, 25, 0),
-	STPMU1_RANGE(1250000, 26, 27, 0),
-	STPMU1_RANGE(1300000, 28, 29, 0),
-	STPMU1_RANGE(1350000, 30, 31, 0),
-	STPMU1_RANGE(1400000, 32, 33, 0),
-	STPMU1_RANGE(1450000, 34, 35, 0),
-	STPMU1_RANGE(1500000, 36, 63, 0),
-};
-
-static const struct stpmu1_range buck3_ranges[] = {
-	STPMU1_RANGE(1000000, 0, 19, 0),
-	STPMU1_RANGE(1100000, 20, 23, 0),
-	STPMU1_RANGE(1200000, 24, 27, 0),
-	STPMU1_RANGE(1300000, 28, 31, 0),
-	STPMU1_RANGE(1400000, 32, 35, 0),
-	STPMU1_RANGE(1500000, 36, 55, 100000),
-	STPMU1_RANGE(3400000, 56, 63, 0),
-};
-
-static const struct stpmu1_range buck4_ranges[] = {
-	STPMU1_RANGE(600000, 0, 27, 25000),
-	STPMU1_RANGE(1300000, 28, 29, 0),
-	STPMU1_RANGE(1350000, 30, 31, 0),
-	STPMU1_RANGE(1400000, 32, 33, 0),
-	STPMU1_RANGE(1450000, 34, 35, 0),
-	STPMU1_RANGE(1500000, 36, 60, 100000),
-	STPMU1_RANGE(3900000, 61, 63, 0),
-};
-
-/* BUCK: 1,2,3,4 - voltage ranges */
-static const struct stpmu1_output_range buck_voltage_range[] = {
-	STPMU1_OUTPUT_RANGE(buck1_ranges, ARRAY_SIZE(buck1_ranges)),
-	STPMU1_OUTPUT_RANGE(buck2_ranges, ARRAY_SIZE(buck2_ranges)),
-	STPMU1_OUTPUT_RANGE(buck3_ranges, ARRAY_SIZE(buck3_ranges)),
-	STPMU1_OUTPUT_RANGE(buck4_ranges, ARRAY_SIZE(buck4_ranges)),
-};
-
-/* BUCK modes */
-static const struct dm_regulator_mode buck_modes[] = {
-	STPMU1_MODE(STPMU1_BUCK_MODE_HP, STPMU1_BUCK_MODE_HP, "HP"),
-	STPMU1_MODE(STPMU1_BUCK_MODE_LP, STPMU1_BUCK_MODE_LP, "LP"),
-};
-
-static int stpmu1_buck_get_uv(struct udevice *dev, int buck)
-{
-	int sel;
-
-	sel = pmic_reg_read(dev, STPMU1_BUCKX_CTRL_REG(buck));
-	if (sel < 0)
-		return sel;
-
-	sel &= STPMU1_BUCK_OUTPUT_MASK;
-	sel >>= STPMU1_BUCK_OUTPUT_SHIFT;
-
-	return stpmu1_output_find_uv(sel, &buck_voltage_range[buck]);
-}
-
-static int stpmu1_buck_get_value(struct udevice *dev)
-{
-	return stpmu1_buck_get_uv(dev->parent, dev->driver_data - 1);
-}
-
-static int stpmu1_buck_set_value(struct udevice *dev, int uv)
-{
-	int sel, buck = dev->driver_data - 1;
-
-	sel = stpmu1_output_find_sel(uv, &buck_voltage_range[buck]);
-	if (sel < 0)
-		return sel;
-
-	return pmic_clrsetbits(dev->parent,
-			       STPMU1_BUCKX_CTRL_REG(buck),
-			       STPMU1_BUCK_OUTPUT_MASK,
-			       sel << STPMU1_BUCK_OUTPUT_SHIFT);
-}
-
-static int stpmu1_buck_get_enable(struct udevice *dev)
-{
-	int ret;
-
-	ret = pmic_reg_read(dev->parent,
-			    STPMU1_BUCKX_CTRL_REG(dev->driver_data - 1));
-	if (ret < 0)
-		return false;
-
-	return ret & STPMU1_BUCK_EN ? true : false;
-}
-
-static int stpmu1_buck_set_enable(struct udevice *dev, bool enable)
-{
-	struct dm_regulator_uclass_platdata *uc_pdata;
-	int delay = enable ? STPMU1_DEFAULT_START_UP_DELAY_MS :
-			     STPMU1_DEFAULT_STOP_DELAY_MS;
-	int ret, uv;
-
-	/* if regulator is already in the wanted state, nothing to do */
-	if (stpmu1_buck_get_enable(dev) == enable)
-		return 0;
-
-	if (enable) {
-		uc_pdata = dev_get_uclass_platdata(dev);
-		uv = stpmu1_buck_get_value(dev);
-		if ((uv < uc_pdata->min_uV) || (uv > uc_pdata->max_uV))
-			stpmu1_buck_set_value(dev, uc_pdata->min_uV);
-	}
-
-	ret = pmic_clrsetbits(dev->parent,
-			      STPMU1_BUCKX_CTRL_REG(dev->driver_data - 1),
-			      STPMU1_BUCK_EN, enable ? STPMU1_BUCK_EN : 0);
-	mdelay(delay);
-
-	return ret;
-}
-
-static int stpmu1_buck_get_mode(struct udevice *dev)
-{
-	int ret;
-
-	ret = pmic_reg_read(dev->parent,
-			    STPMU1_BUCKX_CTRL_REG(dev->driver_data - 1));
-	if (ret < 0)
-		return ret;
-
-	return ret & STPMU1_BUCK_MODE ? STPMU1_BUCK_MODE_LP :
-					 STPMU1_BUCK_MODE_HP;
-}
-
-static int stpmu1_buck_set_mode(struct udevice *dev, int mode)
-{
-	return pmic_clrsetbits(dev->parent,
-			       STPMU1_BUCKX_CTRL_REG(dev->driver_data - 1),
-			       STPMU1_BUCK_MODE,
-			       mode ? STPMU1_BUCK_MODE : 0);
-}
-
-static int stpmu1_buck_probe(struct udevice *dev)
-{
-	struct dm_regulator_uclass_platdata *uc_pdata;
-
-	if (!dev->driver_data || dev->driver_data > STPMU1_MAX_BUCK)
-		return -EINVAL;
-
-	uc_pdata = dev_get_uclass_platdata(dev);
-
-	uc_pdata->type = REGULATOR_TYPE_BUCK;
-	uc_pdata->mode = (struct dm_regulator_mode *)buck_modes;
-	uc_pdata->mode_count = ARRAY_SIZE(buck_modes);
-
-	return 0;
-}
-
-static const struct dm_regulator_ops stpmu1_buck_ops = {
-	.get_value  = stpmu1_buck_get_value,
-	.set_value  = stpmu1_buck_set_value,
-	.get_enable = stpmu1_buck_get_enable,
-	.set_enable = stpmu1_buck_set_enable,
-	.get_mode   = stpmu1_buck_get_mode,
-	.set_mode   = stpmu1_buck_set_mode,
-};
-
-U_BOOT_DRIVER(stpmu1_buck) = {
-	.name = "stpmu1_buck",
-	.id = UCLASS_REGULATOR,
-	.ops = &stpmu1_buck_ops,
-	.probe = stpmu1_buck_probe,
-};
-
-/*
- * LDO regulators
- */
-
-static const struct stpmu1_range ldo12_ranges[] = {
-	STPMU1_RANGE(1700000, 0, 7, 0),
-	STPMU1_RANGE(1700000, 8, 24, 100000),
-	STPMU1_RANGE(3300000, 25, 31, 0),
-};
-
-static const struct stpmu1_range ldo3_ranges[] = {
-	STPMU1_RANGE(1700000, 0, 7, 0),
-	STPMU1_RANGE(1700000, 8, 24, 100000),
-	STPMU1_RANGE(3300000, 25, 30, 0),
-	/* Sel 31 is special case when LDO3 is in mode sync_source (BUCK2/2) */
-};
-
-static const struct stpmu1_range ldo5_ranges[] = {
-	STPMU1_RANGE(1700000, 0, 7, 0),
-	STPMU1_RANGE(1700000, 8, 30, 100000),
-	STPMU1_RANGE(3900000, 31, 31, 0),
-};
-
-static const struct stpmu1_range ldo6_ranges[] = {
-	STPMU1_RANGE(900000, 0, 24, 100000),
-	STPMU1_RANGE(3300000, 25, 31, 0),
-};
-
-/* LDO: 1,2,3,4,5,6 - voltage ranges */
-static const struct stpmu1_output_range ldo_voltage_range[] = {
-	STPMU1_OUTPUT_RANGE(ldo12_ranges, ARRAY_SIZE(ldo12_ranges)),
-	STPMU1_OUTPUT_RANGE(ldo12_ranges, ARRAY_SIZE(ldo12_ranges)),
-	STPMU1_OUTPUT_RANGE(ldo3_ranges, ARRAY_SIZE(ldo3_ranges)),
-	STPMU1_OUTPUT_RANGE(NULL, 0),
-	STPMU1_OUTPUT_RANGE(ldo5_ranges, ARRAY_SIZE(ldo5_ranges)),
-	STPMU1_OUTPUT_RANGE(ldo6_ranges, ARRAY_SIZE(ldo6_ranges)),
-};
-
-/* LDO modes */
-static const struct dm_regulator_mode ldo_modes[] = {
-	STPMU1_MODE(STPMU1_LDO_MODE_NORMAL,
-		    STPMU1_LDO_MODE_NORMAL, "NORMAL"),
-	STPMU1_MODE(STPMU1_LDO_MODE_BYPASS,
-		    STPMU1_LDO_MODE_BYPASS, "BYPASS"),
-	STPMU1_MODE(STPMU1_LDO_MODE_SINK_SOURCE,
-		    STPMU1_LDO_MODE_SINK_SOURCE, "SINK SOURCE"),
-};
-
-static int stpmu1_ldo_get_value(struct udevice *dev)
-{
-	int sel, ldo = dev->driver_data - 1;
-
-	sel = pmic_reg_read(dev->parent, STPMU1_LDOX_CTRL_REG(ldo));
-	if (sel < 0)
-		return sel;
-
-	/* ldo4 => 3,3V */
-	if (ldo == STPMU1_LDO4)
-		return STPMU1_LDO4_UV;
-
-	sel &= STPMU1_LDO12356_OUTPUT_MASK;
-	sel >>= STPMU1_LDO12356_OUTPUT_SHIFT;
-
-	/* ldo3, sel = 31 => BUCK2/2 */
-	if (ldo == STPMU1_LDO3 && sel == STPMU1_LDO3_DDR_SEL)
-		return stpmu1_buck_get_uv(dev->parent, STPMU1_BUCK2) / 2;
-
-	return stpmu1_output_find_uv(sel, &ldo_voltage_range[ldo]);
-}
-
-static int stpmu1_ldo_set_value(struct udevice *dev, int uv)
-{
-	int sel, ldo = dev->driver_data - 1;
-
-	/* ldo4 => not possible */
-	if (ldo == STPMU1_LDO4)
-		return -EINVAL;
-
-	sel = stpmu1_output_find_sel(uv, &ldo_voltage_range[ldo]);
-	if (sel < 0)
-		return sel;
-
-	return pmic_clrsetbits(dev->parent,
-			       STPMU1_LDOX_CTRL_REG(ldo),
-			       STPMU1_LDO12356_OUTPUT_MASK,
-			       sel << STPMU1_LDO12356_OUTPUT_SHIFT);
-}
-
-static int stpmu1_ldo_get_enable(struct udevice *dev)
-{
-	int ret;
-
-	ret = pmic_reg_read(dev->parent,
-			    STPMU1_LDOX_CTRL_REG(dev->driver_data - 1));
-	if (ret < 0)
-		return false;
-
-	return ret & STPMU1_LDO_EN ? true : false;
-}
-
-static int stpmu1_ldo_set_enable(struct udevice *dev, bool enable)
-{
-	struct dm_regulator_uclass_platdata *uc_pdata;
-	int delay = enable ? STPMU1_DEFAULT_START_UP_DELAY_MS :
-			     STPMU1_DEFAULT_STOP_DELAY_MS;
-	int ret, uv;
-
-	/* if regulator is already in the wanted state, nothing to do */
-	if (stpmu1_ldo_get_enable(dev) == enable)
-		return 0;
-
-	if (enable) {
-		uc_pdata = dev_get_uclass_platdata(dev);
-		uv = stpmu1_ldo_get_value(dev);
-		if ((uv < uc_pdata->min_uV) || (uv > uc_pdata->max_uV))
-			stpmu1_ldo_set_value(dev, uc_pdata->min_uV);
-	}
-
-	ret = pmic_clrsetbits(dev->parent,
-			      STPMU1_LDOX_CTRL_REG(dev->driver_data - 1),
-			      STPMU1_LDO_EN, enable ? STPMU1_LDO_EN : 0);
-	mdelay(delay);
-
-	return ret;
-}
-
-static int stpmu1_ldo_get_mode(struct udevice *dev)
-{
-	int ret, ldo = dev->driver_data - 1;
-
-	if (ldo != STPMU1_LDO3)
-		return -EINVAL;
-
-	ret = pmic_reg_read(dev->parent, STPMU1_LDOX_CTRL_REG(ldo));
-	if (ret < 0)
-		return ret;
-
-	if (ret & STPMU1_LDO3_MODE)
-		return STPMU1_LDO_MODE_BYPASS;
-
-	ret &= STPMU1_LDO12356_OUTPUT_MASK;
-	ret >>= STPMU1_LDO12356_OUTPUT_SHIFT;
-
-	return ret == STPMU1_LDO3_DDR_SEL ? STPMU1_LDO_MODE_SINK_SOURCE :
-					     STPMU1_LDO_MODE_NORMAL;
-}
-
-static int stpmu1_ldo_set_mode(struct udevice *dev, int mode)
-{
-	int ret, ldo = dev->driver_data - 1;
-
-	if (ldo != STPMU1_LDO3)
-		return -EINVAL;
-
-	ret = pmic_reg_read(dev->parent, STPMU1_LDOX_CTRL_REG(ldo));
-	if (ret < 0)
-		return ret;
-
-	switch (mode) {
-	case STPMU1_LDO_MODE_SINK_SOURCE:
-		ret &= ~STPMU1_LDO12356_OUTPUT_MASK;
-		ret |= STPMU1_LDO3_DDR_SEL << STPMU1_LDO12356_OUTPUT_SHIFT;
-	case STPMU1_LDO_MODE_NORMAL:
-		ret &= ~STPMU1_LDO3_MODE;
-		break;
-	case STPMU1_LDO_MODE_BYPASS:
-		ret |= STPMU1_LDO3_MODE;
-		break;
-	}
-
-	return pmic_reg_write(dev->parent, STPMU1_LDOX_CTRL_REG(ldo), ret);
-}
-
-static int stpmu1_ldo_probe(struct udevice *dev)
-{
-	struct dm_regulator_uclass_platdata *uc_pdata;
-
-	if (!dev->driver_data || dev->driver_data > STPMU1_MAX_LDO)
-		return -EINVAL;
-
-	uc_pdata = dev_get_uclass_platdata(dev);
-
-	uc_pdata->type = REGULATOR_TYPE_LDO;
-	if (dev->driver_data - 1 == STPMU1_LDO3) {
-		uc_pdata->mode = (struct dm_regulator_mode *)ldo_modes;
-		uc_pdata->mode_count = ARRAY_SIZE(ldo_modes);
-	} else {
-		uc_pdata->mode_count = 0;
-	}
-
-	return 0;
-}
-
-static const struct dm_regulator_ops stpmu1_ldo_ops = {
-	.get_value  = stpmu1_ldo_get_value,
-	.set_value  = stpmu1_ldo_set_value,
-	.get_enable = stpmu1_ldo_get_enable,
-	.set_enable = stpmu1_ldo_set_enable,
-	.get_mode   = stpmu1_ldo_get_mode,
-	.set_mode   = stpmu1_ldo_set_mode,
-};
-
-U_BOOT_DRIVER(stpmu1_ldo) = {
-	.name = "stpmu1_ldo",
-	.id = UCLASS_REGULATOR,
-	.ops = &stpmu1_ldo_ops,
-	.probe = stpmu1_ldo_probe,
-};
-
-/*
- * VREF DDR regulator
- */
-
-static int stpmu1_vref_ddr_get_value(struct udevice *dev)
-{
-	/* BUCK2/2 */
-	return stpmu1_buck_get_uv(dev->parent, STPMU1_BUCK2) / 2;
-}
-
-static int stpmu1_vref_ddr_get_enable(struct udevice *dev)
-{
-	int ret;
-
-	ret = pmic_reg_read(dev->parent, STPMU1_VREF_CTRL_REG);
-	if (ret < 0)
-		return false;
-
-	return ret & STPMU1_VREF_EN ? true : false;
-}
-
-static int stpmu1_vref_ddr_set_enable(struct udevice *dev, bool enable)
-{
-	int delay = enable ? STPMU1_DEFAULT_START_UP_DELAY_MS :
-			     STPMU1_DEFAULT_STOP_DELAY_MS;
-	int ret;
-
-	/* if regulator is already in the wanted state, nothing to do */
-	if (stpmu1_vref_ddr_get_enable(dev) == enable)
-		return 0;
-
-	ret = pmic_clrsetbits(dev->parent, STPMU1_VREF_CTRL_REG,
-			      STPMU1_VREF_EN, enable ? STPMU1_VREF_EN : 0);
-	mdelay(delay);
-
-	return ret;
-}
-
-static int stpmu1_vref_ddr_probe(struct udevice *dev)
-{
-	struct dm_regulator_uclass_platdata *uc_pdata;
-
-	uc_pdata = dev_get_uclass_platdata(dev);
-
-	uc_pdata->type = REGULATOR_TYPE_FIXED;
-	uc_pdata->mode_count = 0;
-
-	return 0;
-}
-
-static const struct dm_regulator_ops stpmu1_vref_ddr_ops = {
-	.get_value  = stpmu1_vref_ddr_get_value,
-	.get_enable = stpmu1_vref_ddr_get_enable,
-	.set_enable = stpmu1_vref_ddr_set_enable,
-};
-
-U_BOOT_DRIVER(stpmu1_vref_ddr) = {
-	.name = "stpmu1_vref_ddr",
-	.id = UCLASS_REGULATOR,
-	.ops = &stpmu1_vref_ddr_ops,
-	.probe = stpmu1_vref_ddr_probe,
-};
-
-/*
- * BOOST regulator
- */
-
-static int stpmu1_boost_get_enable(struct udevice *dev)
-{
-	int ret;
-
-	ret = pmic_reg_read(dev->parent, STPMU1_USB_CTRL_REG);
-	if (ret < 0)
-		return false;
-
-	return ret & STPMU1_USB_BOOST_EN ? true : false;
-}
-
-static int stpmu1_boost_set_enable(struct udevice *dev, bool enable)
-{
-	int ret;
-
-	ret = pmic_reg_read(dev->parent, STPMU1_USB_CTRL_REG);
-	if (ret < 0)
-		return ret;
-
-	if (!enable && ret & STPMU1_USB_PWR_SW_EN)
-		return -EINVAL;
-
-	/* if regulator is already in the wanted state, nothing to do */
-	if (!!(ret & STPMU1_USB_BOOST_EN) == enable)
-		return 0;
-
-	ret = pmic_clrsetbits(dev->parent, STPMU1_USB_CTRL_REG,
-			      STPMU1_USB_BOOST_EN,
-			      enable ? STPMU1_USB_BOOST_EN : 0);
-	if (enable)
-		mdelay(STPMU1_USB_BOOST_START_UP_DELAY_MS);
-
-	return ret;
-}
-
-static int stpmu1_boost_probe(struct udevice *dev)
-{
-	struct dm_regulator_uclass_platdata *uc_pdata;
-
-	uc_pdata = dev_get_uclass_platdata(dev);
-
-	uc_pdata->type = REGULATOR_TYPE_FIXED;
-	uc_pdata->mode_count = 0;
-
-	return 0;
-}
-
-static const struct dm_regulator_ops stpmu1_boost_ops = {
-	.get_enable = stpmu1_boost_get_enable,
-	.set_enable = stpmu1_boost_set_enable,
-};
-
-U_BOOT_DRIVER(stpmu1_boost) = {
-	.name = "stpmu1_boost",
-	.id = UCLASS_REGULATOR,
-	.ops = &stpmu1_boost_ops,
-	.probe = stpmu1_boost_probe,
-};
-
-/*
- * USB power switch
- */
-
-static int stpmu1_pwr_sw_get_enable(struct udevice *dev)
-{
-	uint mask = 1 << dev->driver_data;
-	int ret;
-
-	ret = pmic_reg_read(dev->parent, STPMU1_USB_CTRL_REG);
-	if (ret < 0)
-		return false;
-
-	return ret & mask ? true : false;
-}
-
-static int stpmu1_pwr_sw_set_enable(struct udevice *dev, bool enable)
-{
-	uint mask = 1 << dev->driver_data;
-	int delay = enable ? STPMU1_DEFAULT_START_UP_DELAY_MS :
-			     STPMU1_DEFAULT_STOP_DELAY_MS;
-	int ret;
-
-	ret = pmic_reg_read(dev->parent, STPMU1_USB_CTRL_REG);
-	if (ret < 0)
-		return ret;
-
-	/* if regulator is already in the wanted state, nothing to do */
-	if (!!(ret & mask) == enable)
-		return 0;
-
-	/* Boost management */
-	if (enable && !(ret & STPMU1_USB_BOOST_EN)) {
-		pmic_clrsetbits(dev->parent, STPMU1_USB_CTRL_REG,
-				STPMU1_USB_BOOST_EN, STPMU1_USB_BOOST_EN);
-		mdelay(STPMU1_USB_BOOST_START_UP_DELAY_MS);
-	} else if (!enable && ret & STPMU1_USB_BOOST_EN &&
-		   (ret & STPMU1_USB_PWR_SW_EN) != STPMU1_USB_PWR_SW_EN) {
-		pmic_clrsetbits(dev->parent, STPMU1_USB_CTRL_REG,
-				STPMU1_USB_BOOST_EN, 0);
-	}
-
-	ret = pmic_clrsetbits(dev->parent, STPMU1_USB_CTRL_REG,
-			      mask, enable ? mask : 0);
-	mdelay(delay);
-
-	return ret;
-}
-
-static int stpmu1_pwr_sw_probe(struct udevice *dev)
-{
-	struct dm_regulator_uclass_platdata *uc_pdata;
-
-	if (!dev->driver_data || dev->driver_data > STPMU1_MAX_PWR_SW)
-		return -EINVAL;
-
-	uc_pdata = dev_get_uclass_platdata(dev);
-
-	uc_pdata->type = REGULATOR_TYPE_FIXED;
-	uc_pdata->mode_count = 0;
-
-	return 0;
-}
-
-static const struct dm_regulator_ops stpmu1_pwr_sw_ops = {
-	.get_enable = stpmu1_pwr_sw_get_enable,
-	.set_enable = stpmu1_pwr_sw_set_enable,
-};
-
-U_BOOT_DRIVER(stpmu1_pwr_sw) = {
-	.name = "stpmu1_pwr_sw",
-	.id = UCLASS_REGULATOR,
-	.ops = &stpmu1_pwr_sw_ops,
-	.probe = stpmu1_pwr_sw_probe,
-};
diff --git a/drivers/ram/stm32mp1/stm32mp1_ram.c b/drivers/ram/stm32mp1/stm32mp1_ram.c
index bd497a3..e45a3b2 100644
--- a/drivers/ram/stm32mp1/stm32mp1_ram.c
+++ b/drivers/ram/stm32mp1/stm32mp1_ram.c
@@ -157,7 +157,8 @@
 
 	priv->info.base = STM32_DDR_BASE;
 
-#if !defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD)
+#if !defined(CONFIG_STM32MP1_TRUSTED) && \
+	(!defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD))
 	priv->info.size = 0;
 	return stm32mp1_ddr_setup(dev);
 #else
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 098372e..a700f24 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -222,8 +222,7 @@
 
 config STM32_QSPI
 	bool "STM32F7 QSPI driver"
-	depends on STM32F7
-	imply SPI_FLASH_BAR
+	depends on STM32F7 || ARCH_STM32MP
 	help
 	  Enable the STM32F7 Quad-SPI (QSPI) driver. This driver can be
 	  used to access the SPI NOR flash chips on platforms embedding
diff --git a/drivers/spi/cadence_qspi.c b/drivers/spi/cadence_qspi.c
index 11fce9c..efdb178 100644
--- a/drivers/spi/cadence_qspi.c
+++ b/drivers/spi/cadence_qspi.c
@@ -256,7 +256,7 @@
 		break;
 		case CQSPI_INDIRECT_WRITE:
 			err = cadence_qspi_apb_indirect_write_setup
-				(plat, priv->cmd_len, cmd_buf);
+				(plat, priv->cmd_len, dm_plat->mode, cmd_buf);
 			if (!err) {
 				err = cadence_qspi_apb_indirect_write_execute
 				(plat, data_bytes, dout);
diff --git a/drivers/spi/cadence_qspi.h b/drivers/spi/cadence_qspi.h
index 055900d..b491407 100644
--- a/drivers/spi/cadence_qspi.h
+++ b/drivers/spi/cadence_qspi.h
@@ -60,7 +60,7 @@
 int cadence_qspi_apb_indirect_read_execute(struct cadence_spi_platdata *plat,
 	unsigned int rxlen, u8 *rxbuf);
 int cadence_qspi_apb_indirect_write_setup(struct cadence_spi_platdata *plat,
-	unsigned int cmdlen, const u8 *cmdbuf);
+	unsigned int cmdlen, unsigned int tx_width, const u8 *cmdbuf);
 int cadence_qspi_apb_indirect_write_execute(struct cadence_spi_platdata *plat,
 	unsigned int txlen, const u8 *txbuf);
 
diff --git a/drivers/spi/cadence_qspi_apb.c b/drivers/spi/cadence_qspi_apb.c
index a8af352..55a7501 100644
--- a/drivers/spi/cadence_qspi_apb.c
+++ b/drivers/spi/cadence_qspi_apb.c
@@ -77,6 +77,7 @@
 
 #define	CQSPI_REG_WR_INSTR			0x08
 #define	CQSPI_REG_WR_INSTR_OPCODE_LSB		0
+#define	CQSPI_REG_WR_INSTR_TYPE_DATA_LSB	16
 
 #define	CQSPI_REG_DELAY				0x0C
 #define	CQSPI_REG_DELAY_TSLCH_LSB		0
@@ -686,7 +687,7 @@
 
 /* Opcode + Address (3/4 bytes) */
 int cadence_qspi_apb_indirect_write_setup(struct cadence_spi_platdata *plat,
-	unsigned int cmdlen, const u8 *cmdbuf)
+	unsigned int cmdlen, unsigned int tx_width, const u8 *cmdbuf)
 {
 	unsigned int reg;
 	unsigned int addr_bytes = cmdlen > 4 ? 4 : 3;
@@ -702,6 +703,10 @@
 
 	/* Configure the opcode */
 	reg = cmdbuf[0] << CQSPI_REG_WR_INSTR_OPCODE_LSB;
+
+	if (tx_width & SPI_TX_QUAD)
+		reg |= CQSPI_INST_TYPE_QUAD << CQSPI_REG_WR_INSTR_TYPE_DATA_LSB;
+
 	writel(reg, plat->regbase + CQSPI_REG_WR_INSTR);
 
 	/* Setup write address. */
diff --git a/drivers/spi/fsl_dspi.c b/drivers/spi/fsl_dspi.c
index 764c942..a68a519 100644
--- a/drivers/spi/fsl_dspi.c
+++ b/drivers/spi/fsl_dspi.c
@@ -273,7 +273,18 @@
 	if (len > 1) {
 		int tmp_len = len - 1;
 		while (tmp_len--) {
-			if (dout != NULL) {
+			if ((dout != NULL) && (din != NULL)) {
+				if (priv->charbit == 16) {
+					dspi_tx(priv, ctrl, *spi_wr16++);
+					*spi_rd16++ = dspi_rx(priv);
+				}
+				else {
+					dspi_tx(priv, ctrl, *spi_wr++);
+					*spi_rd++ = dspi_rx(priv);
+				}
+			}
+
+			else if (dout != NULL) {
 				if (priv->charbit == 16)
 					dspi_tx(priv, ctrl, *spi_wr16++);
 				else
@@ -281,7 +292,7 @@
 				dspi_rx(priv);
 			}
 
-			if (din != NULL) {
+			else if (din != NULL) {
 				dspi_tx(priv, ctrl, DSPI_IDLE_VAL);
 				if (priv->charbit == 16)
 					*spi_rd16++ = dspi_rx(priv);
@@ -297,7 +308,18 @@
 		ctrl &= ~DSPI_TFR_CONT;
 
 	if (len) {
-		if (dout != NULL) {
+		if ((dout != NULL) && (din != NULL)) {
+			if (priv->charbit == 16) {
+				dspi_tx(priv, ctrl, *spi_wr16++);
+				*spi_rd16++ = dspi_rx(priv);
+			}
+			else {
+				dspi_tx(priv, ctrl, *spi_wr++);
+				*spi_rd++ = dspi_rx(priv);
+			}
+		}
+
+		else if (dout != NULL) {
 			if (priv->charbit == 16)
 				dspi_tx(priv, ctrl, *spi_wr16);
 			else
@@ -305,7 +327,7 @@
 			dspi_rx(priv);
 		}
 
-		if (din != NULL) {
+		else if (din != NULL) {
 			dspi_tx(priv, ctrl, DSPI_IDLE_VAL);
 			if (priv->charbit == 16)
 				*spi_rd16 = dspi_rx(priv);
diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c
index 1bb0987..b86eee7 100644
--- a/drivers/spi/spi-mem.c
+++ b/drivers/spi/spi-mem.c
@@ -214,7 +214,7 @@
 	if (ret < 0)
 		return ret;
 
-	if (ops->mem_ops) {
+	if (ops->mem_ops && ops->mem_ops->exec_op) {
 #ifndef __UBOOT__
 		/*
 		 * Flush the message queue before executing our SPI memory
diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c
index 2bc289a..88cb2a1 100644
--- a/drivers/spi/spi-uclass.c
+++ b/drivers/spi/spi-uclass.c
@@ -328,7 +328,9 @@
 	}
 
 	plat = dev_get_parent_platdata(dev);
-	if (!speed) {
+
+	/* get speed and mode from platdata when available */
+	if (plat->max_hz) {
 		speed = plat->max_hz;
 		mode = plat->mode;
 	}
diff --git a/drivers/spi/stm32_qspi.c b/drivers/spi/stm32_qspi.c
index 8b60d7c..bb1067f 100644
--- a/drivers/spi/stm32_qspi.c
+++ b/drivers/spi/stm32_qspi.c
@@ -9,15 +9,11 @@
 
 #include <common.h>
 #include <clk.h>
-#include <dm.h>
-#include <errno.h>
-#include <malloc.h>
 #include <reset.h>
-#include <spi.h>
-#include <spi_flash.h>
-#include <asm/io.h>
-#include <asm/arch/stm32.h>
+#include <spi-mem.h>
+#include <linux/iopoll.h>
 #include <linux/ioport.h>
+#include <linux/sizes.h>
 
 struct stm32_qspi_regs {
 	u32 cr;		/* 0x00 */
@@ -45,8 +41,7 @@
 #define STM32_QSPI_CR_SSHIFT		BIT(4)
 #define STM32_QSPI_CR_DFM		BIT(6)
 #define STM32_QSPI_CR_FSEL		BIT(7)
-#define STM32_QSPI_CR_FTHRES_MASK	GENMASK(4, 0)
-#define STM32_QSPI_CR_FTHRES_SHIFT	(8)
+#define STM32_QSPI_CR_FTHRES_SHIFT	8
 #define STM32_QSPI_CR_TEIE		BIT(16)
 #define STM32_QSPI_CR_TCIE		BIT(17)
 #define STM32_QSPI_CR_FTIE		BIT(18)
@@ -55,16 +50,16 @@
 #define STM32_QSPI_CR_APMS		BIT(22)
 #define STM32_QSPI_CR_PMM		BIT(23)
 #define STM32_QSPI_CR_PRESCALER_MASK	GENMASK(7, 0)
-#define STM32_QSPI_CR_PRESCALER_SHIFT	(24)
+#define STM32_QSPI_CR_PRESCALER_SHIFT	24
 
 /*
  * QUADSPI device configuration register
  */
 #define STM32_QSPI_DCR_CKMODE		BIT(0)
 #define STM32_QSPI_DCR_CSHT_MASK	GENMASK(2, 0)
-#define STM32_QSPI_DCR_CSHT_SHIFT	(8)
+#define STM32_QSPI_DCR_CSHT_SHIFT	8
 #define STM32_QSPI_DCR_FSIZE_MASK	GENMASK(4, 0)
-#define STM32_QSPI_DCR_FSIZE_SHIFT	(16)
+#define STM32_QSPI_DCR_FSIZE_SHIFT	16
 
 /*
  * QUADSPI status register
@@ -75,8 +70,6 @@
 #define STM32_QSPI_SR_SMF		BIT(3)
 #define STM32_QSPI_SR_TOF		BIT(4)
 #define STM32_QSPI_SR_BUSY		BIT(5)
-#define STM32_QSPI_SR_FLEVEL_MASK	GENMASK(5, 0)
-#define STM32_QSPI_SR_FLEVEL_SHIFT	(8)
 
 /*
  * QUADSPI flag clear register
@@ -92,388 +85,276 @@
 #define STM32_QSPI_CCR_DDRM		BIT(31)
 #define STM32_QSPI_CCR_DHHC		BIT(30)
 #define STM32_QSPI_CCR_SIOO		BIT(28)
-#define STM32_QSPI_CCR_FMODE_SHIFT	(26)
-#define STM32_QSPI_CCR_DMODE_SHIFT	(24)
-#define STM32_QSPI_CCR_DCYC_SHIFT	(18)
-#define STM32_QSPI_CCR_DCYC_MASK	GENMASK(4, 0)
-#define STM32_QSPI_CCR_ABSIZE_SHIFT	(16)
-#define STM32_QSPI_CCR_ABMODE_SHIFT	(14)
-#define STM32_QSPI_CCR_ADSIZE_SHIFT	(12)
-#define STM32_QSPI_CCR_ADMODE_SHIFT	(10)
-#define STM32_QSPI_CCR_IMODE_SHIFT	(8)
-#define STM32_QSPI_CCR_INSTRUCTION_MASK	GENMASK(7, 0)
+#define STM32_QSPI_CCR_FMODE_SHIFT	26
+#define STM32_QSPI_CCR_DMODE_SHIFT	24
+#define STM32_QSPI_CCR_DCYC_SHIFT	18
+#define STM32_QSPI_CCR_ABSIZE_SHIFT	16
+#define STM32_QSPI_CCR_ABMODE_SHIFT	14
+#define STM32_QSPI_CCR_ADSIZE_SHIFT	12
+#define STM32_QSPI_CCR_ADMODE_SHIFT	10
+#define STM32_QSPI_CCR_IMODE_SHIFT	8
 
-enum STM32_QSPI_CCR_IMODE {
-	STM32_QSPI_CCR_IMODE_NONE = 0,
-	STM32_QSPI_CCR_IMODE_ONE_LINE = 1,
-	STM32_QSPI_CCR_IMODE_TWO_LINE = 2,
-	STM32_QSPI_CCR_IMODE_FOUR_LINE = 3,
-};
-
-enum STM32_QSPI_CCR_ADMODE {
-	STM32_QSPI_CCR_ADMODE_NONE = 0,
-	STM32_QSPI_CCR_ADMODE_ONE_LINE = 1,
-	STM32_QSPI_CCR_ADMODE_TWO_LINE = 2,
-	STM32_QSPI_CCR_ADMODE_FOUR_LINE = 3,
-};
-
-enum STM32_QSPI_CCR_ADSIZE {
-	STM32_QSPI_CCR_ADSIZE_8BIT = 0,
-	STM32_QSPI_CCR_ADSIZE_16BIT = 1,
-	STM32_QSPI_CCR_ADSIZE_24BIT = 2,
-	STM32_QSPI_CCR_ADSIZE_32BIT = 3,
-};
+#define STM32_QSPI_CCR_IND_WRITE	0
+#define STM32_QSPI_CCR_IND_READ		1
+#define STM32_QSPI_CCR_MEM_MAP		3
 
-enum STM32_QSPI_CCR_ABMODE {
-	STM32_QSPI_CCR_ABMODE_NONE = 0,
-	STM32_QSPI_CCR_ABMODE_ONE_LINE = 1,
-	STM32_QSPI_CCR_ABMODE_TWO_LINE = 2,
-	STM32_QSPI_CCR_ABMODE_FOUR_LINE = 3,
-};
+#define STM32_QSPI_MAX_MMAP_SZ		SZ_256M
+#define STM32_QSPI_MAX_CHIP		2
 
-enum STM32_QSPI_CCR_ABSIZE {
-	STM32_QSPI_CCR_ABSIZE_8BIT = 0,
-	STM32_QSPI_CCR_ABSIZE_16BIT = 1,
-	STM32_QSPI_CCR_ABSIZE_24BIT = 2,
-	STM32_QSPI_CCR_ABSIZE_32BIT = 3,
-};
+#define STM32_QSPI_FIFO_TIMEOUT_US	30000
+#define STM32_QSPI_CMD_TIMEOUT_US	1000000
+#define STM32_BUSY_TIMEOUT_US		100000
+#define STM32_ABT_TIMEOUT_US		100000
 
-enum STM32_QSPI_CCR_DMODE {
-	STM32_QSPI_CCR_DMODE_NONE = 0,
-	STM32_QSPI_CCR_DMODE_ONE_LINE = 1,
-	STM32_QSPI_CCR_DMODE_TWO_LINE = 2,
-	STM32_QSPI_CCR_DMODE_FOUR_LINE = 3,
+struct stm32_qspi_flash {
+	u32 cr;
+	u32 dcr;
+	bool initialized;
 };
 
-enum STM32_QSPI_CCR_FMODE {
-	STM32_QSPI_CCR_IND_WRITE = 0,
-	STM32_QSPI_CCR_IND_READ = 1,
-	STM32_QSPI_CCR_AUTO_POLL = 2,
-	STM32_QSPI_CCR_MEM_MAP = 3,
-};
-
-/* default SCK frequency, unit: HZ */
-#define STM32_QSPI_DEFAULT_SCK_FREQ 108000000
-
-#define STM32_MAX_NORCHIP 2
-
-struct stm32_qspi_platdata {
-	u32 base;
-	u32 memory_map;
-	u32 max_hz;
-};
-
 struct stm32_qspi_priv {
 	struct stm32_qspi_regs *regs;
+	struct stm32_qspi_flash flash[STM32_QSPI_MAX_CHIP];
+	void __iomem *mm_base;
+	resource_size_t mm_size;
 	ulong clock_rate;
-	u32 max_hz;
-	u32 mode;
-
-	u32 command;
-	u32 address;
-	u32 dummycycles;
-#define CMD_HAS_ADR	BIT(24)
-#define CMD_HAS_DUMMY	BIT(25)
-#define CMD_HAS_DATA	BIT(26)
+	int cs_used;
 };
 
-static void _stm32_qspi_disable(struct stm32_qspi_priv *priv)
+static int _stm32_qspi_wait_for_not_busy(struct stm32_qspi_priv *priv)
 {
-	clrbits_le32(&priv->regs->cr, STM32_QSPI_CR_EN);
-}
+	u32 sr;
+	int ret;
 
-static void _stm32_qspi_enable(struct stm32_qspi_priv *priv)
-{
-	setbits_le32(&priv->regs->cr, STM32_QSPI_CR_EN);
-}
+	ret = readl_poll_timeout(&priv->regs->sr, sr,
+				 !(sr & STM32_QSPI_SR_BUSY),
+				 STM32_BUSY_TIMEOUT_US);
+	if (ret)
+		pr_err("busy timeout (stat:%#x)\n", sr);
 
-static void _stm32_qspi_wait_for_not_busy(struct stm32_qspi_priv *priv)
-{
-	while (readl(&priv->regs->sr) & STM32_QSPI_SR_BUSY)
-		;
+	return ret;
 }
 
-static void _stm32_qspi_wait_for_complete(struct stm32_qspi_priv *priv)
+static int _stm32_qspi_wait_cmd(struct stm32_qspi_priv *priv,
+				const struct spi_mem_op *op)
 {
-	while (!(readl(&priv->regs->sr) & STM32_QSPI_SR_TCF))
-		;
-}
+	u32 sr;
+	int ret;
 
-static void _stm32_qspi_wait_for_ftf(struct stm32_qspi_priv *priv)
-{
-	while (!(readl(&priv->regs->sr) & STM32_QSPI_SR_FTF))
-		;
+	if (!op->data.nbytes)
+		return _stm32_qspi_wait_for_not_busy(priv);
+
+	ret = readl_poll_timeout(&priv->regs->sr, sr,
+				 sr & STM32_QSPI_SR_TCF,
+				 STM32_QSPI_CMD_TIMEOUT_US);
+	if (ret) {
+		pr_err("cmd timeout (stat:%#x)\n", sr);
+	} else if (readl(&priv->regs->sr) & STM32_QSPI_SR_TEF) {
+		pr_err("transfer error (stat:%#x)\n", sr);
+		ret = -EIO;
+	}
+
+	/* clear flags */
+	writel(STM32_QSPI_FCR_CTCF | STM32_QSPI_FCR_CTEF, &priv->regs->fcr);
+
+	return ret;
 }
 
-static void _stm32_qspi_set_flash_size(struct stm32_qspi_priv *priv, u32 size)
+static void _stm32_qspi_read_fifo(u8 *val, void __iomem *addr)
 {
-	u32 fsize = fls(size) - 1;
-
-	clrsetbits_le32(&priv->regs->dcr,
-			STM32_QSPI_DCR_FSIZE_MASK << STM32_QSPI_DCR_FSIZE_SHIFT,
-			fsize << STM32_QSPI_DCR_FSIZE_SHIFT);
+	*val = readb(addr);
 }
 
-static void _stm32_qspi_set_cs(struct stm32_qspi_priv *priv, unsigned int cs)
+static void _stm32_qspi_write_fifo(u8 *val, void __iomem *addr)
 {
-	clrsetbits_le32(&priv->regs->cr, STM32_QSPI_CR_FSEL,
-			cs ? STM32_QSPI_CR_FSEL : 0);
+	writeb(*val, addr);
 }
 
-static unsigned int _stm32_qspi_gen_ccr(struct stm32_qspi_priv *priv, u8 fmode)
+static int _stm32_qspi_poll(struct stm32_qspi_priv *priv,
+			    const struct spi_mem_op *op)
 {
-	unsigned int ccr_reg = 0;
-	u8 imode, admode, dmode;
-	u32 mode = priv->mode;
-	u32 cmd = (priv->command & STM32_QSPI_CCR_INSTRUCTION_MASK);
+	void (*fifo)(u8 *val, void __iomem *addr);
+	u32 len = op->data.nbytes, sr;
+	u8 *buf;
+	int ret;
 
-	imode = STM32_QSPI_CCR_IMODE_ONE_LINE;
-	admode = STM32_QSPI_CCR_ADMODE_ONE_LINE;
-	dmode = STM32_QSPI_CCR_DMODE_ONE_LINE;
+	if (op->data.dir == SPI_MEM_DATA_IN) {
+		fifo = _stm32_qspi_read_fifo;
+		buf = op->data.buf.in;
 
-	if ((priv->command & CMD_HAS_ADR) && (priv->command & CMD_HAS_DATA)) {
-		if (fmode == STM32_QSPI_CCR_IND_WRITE) {
-			if (mode & SPI_TX_QUAD)
-				dmode = STM32_QSPI_CCR_DMODE_FOUR_LINE;
-			else if (mode & SPI_TX_DUAL)
-				dmode = STM32_QSPI_CCR_DMODE_TWO_LINE;
-		} else if ((fmode == STM32_QSPI_CCR_MEM_MAP) ||
-			 (fmode == STM32_QSPI_CCR_IND_READ)) {
-			if (mode & SPI_RX_QUAD)
-				dmode = STM32_QSPI_CCR_DMODE_FOUR_LINE;
-			else if (mode & SPI_RX_DUAL)
-				dmode = STM32_QSPI_CCR_DMODE_TWO_LINE;
-		}
+	} else {
+		fifo = _stm32_qspi_write_fifo;
+		buf = (u8 *)op->data.buf.out;
 	}
 
-	if (priv->command & CMD_HAS_DATA)
-		ccr_reg |= (dmode << STM32_QSPI_CCR_DMODE_SHIFT);
-
-	if (priv->command & CMD_HAS_DUMMY)
-		ccr_reg |= ((priv->dummycycles & STM32_QSPI_CCR_DCYC_MASK)
-				<< STM32_QSPI_CCR_DCYC_SHIFT);
+	while (len--) {
+		ret = readl_poll_timeout(&priv->regs->sr, sr,
+					 sr & STM32_QSPI_SR_FTF,
+					 STM32_QSPI_FIFO_TIMEOUT_US);
+		if (ret) {
+			pr_err("fifo timeout (len:%d stat:%#x)\n", len, sr);
+			return ret;
+		}
 
-	if (priv->command & CMD_HAS_ADR) {
-		ccr_reg |= (STM32_QSPI_CCR_ADSIZE_24BIT
-				<< STM32_QSPI_CCR_ADSIZE_SHIFT);
-		ccr_reg |= (admode << STM32_QSPI_CCR_ADMODE_SHIFT);
+		fifo(buf++, &priv->regs->dr);
 	}
 
-	ccr_reg |= (fmode << STM32_QSPI_CCR_FMODE_SHIFT);
-	ccr_reg |= (imode << STM32_QSPI_CCR_IMODE_SHIFT);
-	ccr_reg |= cmd;
-
-	return ccr_reg;
+	return 0;
 }
 
-static void _stm32_qspi_enable_mmap(struct stm32_qspi_priv *priv,
-				    struct spi_flash *flash)
+static int stm32_qspi_mm(struct stm32_qspi_priv *priv,
+			 const struct spi_mem_op *op)
 {
-	unsigned int ccr_reg;
-
-	priv->command = flash->read_opcode | CMD_HAS_ADR | CMD_HAS_DATA
-			| CMD_HAS_DUMMY;
-	priv->dummycycles = flash->read_dummy;
+	memcpy_fromio(op->data.buf.in, priv->mm_base + op->addr.val,
+		      op->data.nbytes);
 
-	ccr_reg = _stm32_qspi_gen_ccr(priv, STM32_QSPI_CCR_MEM_MAP);
-
-	_stm32_qspi_wait_for_not_busy(priv);
-
-	writel(ccr_reg, &priv->regs->ccr);
-
-	priv->dummycycles = 0;
+	return 0;
 }
 
-static void _stm32_qspi_disable_mmap(struct stm32_qspi_priv *priv)
+static int _stm32_qspi_tx(struct stm32_qspi_priv *priv,
+			  const struct spi_mem_op *op,
+			  u8 mode)
 {
-	setbits_le32(&priv->regs->cr, STM32_QSPI_CR_ABORT);
-}
+	if (!op->data.nbytes)
+		return 0;
 
-static void _stm32_qspi_set_xfer_length(struct stm32_qspi_priv *priv,
-					u32 length)
-{
-	writel(length - 1, &priv->regs->dlr);
+	if (mode == STM32_QSPI_CCR_MEM_MAP)
+		return stm32_qspi_mm(priv, op);
+
+	return _stm32_qspi_poll(priv, op);
 }
 
-static void _stm32_qspi_start_xfer(struct stm32_qspi_priv *priv, u32 cr_reg)
+static int _stm32_qspi_get_mode(u8 buswidth)
 {
-	writel(cr_reg, &priv->regs->ccr);
+	if (buswidth == 4)
+		return 3;
 
-	if (priv->command & CMD_HAS_ADR)
-		writel(priv->address, &priv->regs->ar);
+	return buswidth;
 }
 
-static int _stm32_qspi_xfer(struct stm32_qspi_priv *priv,
-			    struct spi_flash *flash, unsigned int bitlen,
-			    const u8 *dout, u8 *din, unsigned long flags)
+static int stm32_qspi_exec_op(struct spi_slave *slave,
+			      const struct spi_mem_op *op)
 {
-	unsigned int words = bitlen / 8;
-	u32 ccr_reg;
-	int i;
+	struct stm32_qspi_priv *priv = dev_get_priv(slave->dev->parent);
+	u32 cr, ccr, addr_max;
+	u8 mode = STM32_QSPI_CCR_IND_WRITE;
+	int timeout, ret;
 
-	if (flags & SPI_XFER_MMAP) {
-		_stm32_qspi_enable_mmap(priv, flash);
-		return 0;
-	} else if (flags & SPI_XFER_MMAP_END) {
-		_stm32_qspi_disable_mmap(priv);
-		return 0;
-	}
-
-	if (bitlen == 0)
-		return -1;
+	debug("%s: cmd:%#x mode:%d.%d.%d.%d addr:%#llx len:%#x\n",
+	      __func__, op->cmd.opcode, op->cmd.buswidth, op->addr.buswidth,
+	      op->dummy.buswidth, op->data.buswidth,
+	      op->addr.val, op->data.nbytes);
 
-	if (bitlen % 8) {
-		debug("spi_xfer: Non byte aligned SPI transfer\n");
-		return -1;
-	}
+	ret = _stm32_qspi_wait_for_not_busy(priv);
+	if (ret)
+		return ret;
 
-	if (dout && din) {
-		debug("spi_xfer: QSPI cannot have data in and data out set\n");
-		return -1;
-	}
+	addr_max = op->addr.val + op->data.nbytes + 1;
 
-	if (!dout && (flags & SPI_XFER_BEGIN)) {
-		debug("spi_xfer: QSPI transfer must begin with command\n");
-		return -1;
+	if (op->data.dir == SPI_MEM_DATA_IN && op->data.nbytes) {
+		if (addr_max < priv->mm_size && op->addr.buswidth)
+			mode = STM32_QSPI_CCR_MEM_MAP;
+		else
+			mode = STM32_QSPI_CCR_IND_READ;
 	}
 
-	if (dout) {
-		if (flags & SPI_XFER_BEGIN) {
-			/* data is command */
-			priv->command = dout[0] | CMD_HAS_DATA;
-			if (words >= 4) {
-				/* address is here too */
-				priv->address = (dout[1] << 16) |
-						(dout[2] << 8) | dout[3];
-				priv->command |= CMD_HAS_ADR;
-			}
-
-			if (words > 4) {
-				/* rest is dummy bytes */
-				priv->dummycycles = (words - 4) * 8;
-				priv->command |= CMD_HAS_DUMMY;
-			}
-
-			if (flags & SPI_XFER_END) {
-				/* command without data */
-				priv->command &= ~(CMD_HAS_DATA);
-			}
-		}
-
-		if (flags & SPI_XFER_END) {
-			ccr_reg = _stm32_qspi_gen_ccr(priv,
-						      STM32_QSPI_CCR_IND_WRITE);
+	if (op->data.nbytes)
+		writel(op->data.nbytes - 1, &priv->regs->dlr);
 
-			_stm32_qspi_wait_for_not_busy(priv);
+	ccr = (mode << STM32_QSPI_CCR_FMODE_SHIFT);
+	ccr |= op->cmd.opcode;
+	ccr |= (_stm32_qspi_get_mode(op->cmd.buswidth)
+		<< STM32_QSPI_CCR_IMODE_SHIFT);
 
-			if (priv->command & CMD_HAS_DATA)
-				_stm32_qspi_set_xfer_length(priv, words);
-
-			_stm32_qspi_start_xfer(priv, ccr_reg);
-
-			debug("%s: write: ccr:0x%08x adr:0x%08x\n",
-			      __func__, priv->regs->ccr, priv->regs->ar);
-
-			if (priv->command & CMD_HAS_DATA) {
-				_stm32_qspi_wait_for_ftf(priv);
-
-				debug("%s: words:%d data:", __func__, words);
-
-				i = 0;
-				while (words > i) {
-					writeb(dout[i], &priv->regs->dr);
-					debug("%02x ", dout[i]);
-					i++;
-				}
-				debug("\n");
+	if (op->addr.nbytes) {
+		ccr |= ((op->addr.nbytes - 1) << STM32_QSPI_CCR_ADSIZE_SHIFT);
+		ccr |= (_stm32_qspi_get_mode(op->addr.buswidth)
+			<< STM32_QSPI_CCR_ADMODE_SHIFT);
+	}
 
-				_stm32_qspi_wait_for_complete(priv);
-			} else {
-				_stm32_qspi_wait_for_not_busy(priv);
-			}
-		}
-	} else if (din) {
-		ccr_reg = _stm32_qspi_gen_ccr(priv, STM32_QSPI_CCR_IND_READ);
+	if (op->dummy.buswidth && op->dummy.nbytes)
+		ccr |= (op->dummy.nbytes * 8 / op->dummy.buswidth
+			<< STM32_QSPI_CCR_DCYC_SHIFT);
 
-		_stm32_qspi_wait_for_not_busy(priv);
+	if (op->data.nbytes)
+		ccr |= (_stm32_qspi_get_mode(op->data.buswidth)
+			<< STM32_QSPI_CCR_DMODE_SHIFT);
 
-		_stm32_qspi_set_xfer_length(priv, words);
+	writel(ccr, &priv->regs->ccr);
 
-		_stm32_qspi_start_xfer(priv, ccr_reg);
+	if (op->addr.nbytes && mode != STM32_QSPI_CCR_MEM_MAP)
+		writel(op->addr.val, &priv->regs->ar);
 
-		debug("%s: read: ccr:0x%08x adr:0x%08x len:%d\n", __func__,
-		      priv->regs->ccr, priv->regs->ar, priv->regs->dlr);
+	ret = _stm32_qspi_tx(priv, op, mode);
+	/*
+	 * Abort in:
+	 * -error case
+	 * -read memory map: prefetching must be stopped if we read the last
+	 *  byte of device (device size - fifo size). like device size is not
+	 *  knows, the prefetching is always stop.
+	 */
+	if (ret || mode == STM32_QSPI_CCR_MEM_MAP)
+		goto abort;
 
-		debug("%s: data:", __func__);
-
-		i = 0;
-		while (words > i) {
-			din[i] = readb(&priv->regs->dr);
-			debug("%02x ", din[i]);
-			i++;
-		}
-		debug("\n");
-	}
+	/* Wait end of tx in indirect mode */
+	ret = _stm32_qspi_wait_cmd(priv, op);
+	if (ret)
+		goto abort;
 
 	return 0;
-}
 
-static int stm32_qspi_ofdata_to_platdata(struct udevice *bus)
-{
-	struct resource res_regs, res_mem;
-	struct stm32_qspi_platdata *plat = bus->platdata;
-	int ret;
-
-	ret = dev_read_resource_byname(bus, "qspi", &res_regs);
-	if (ret) {
-		debug("Error: can't get regs base addresses(ret = %d)!\n", ret);
-		return -ENOMEM;
-	}
-	ret = dev_read_resource_byname(bus, "qspi_mm", &res_mem);
-	if (ret) {
-		debug("Error: can't get mmap base address(ret = %d)!\n", ret);
-		return -ENOMEM;
-	}
+abort:
+	setbits_le32(&priv->regs->cr, STM32_QSPI_CR_ABORT);
 
-	plat->max_hz = dev_read_u32_default(bus, "spi-max-frequency",
-					    STM32_QSPI_DEFAULT_SCK_FREQ);
+	/* Wait clear of abort bit by hw */
+	timeout = readl_poll_timeout(&priv->regs->cr, cr,
+				     !(cr & STM32_QSPI_CR_ABORT),
+				     STM32_ABT_TIMEOUT_US);
 
-	plat->base = res_regs.start;
-	plat->memory_map = res_mem.start;
+	writel(STM32_QSPI_FCR_CTCF, &priv->regs->fcr);
 
-	debug("%s: regs=<0x%x> mapped=<0x%x>, max-frequency=%d\n",
-	      __func__,
-	      plat->base,
-	      plat->memory_map,
-	      plat->max_hz
-	      );
+	if (ret || timeout)
+		pr_err("%s ret:%d abort timeout:%d\n", __func__, ret, timeout);
 
-	return 0;
+	return ret;
 }
 
 static int stm32_qspi_probe(struct udevice *bus)
 {
-	struct stm32_qspi_platdata *plat = dev_get_platdata(bus);
 	struct stm32_qspi_priv *priv = dev_get_priv(bus);
-	struct dm_spi_bus *dm_spi_bus;
+	struct resource res;
 	struct clk clk;
 	struct reset_ctl reset_ctl;
 	int ret;
 
-	dm_spi_bus = bus->uclass_priv;
+	ret = dev_read_resource_byname(bus, "qspi", &res);
+	if (ret) {
+		dev_err(bus, "can't get regs base addresses(ret = %d)!\n", ret);
+		return ret;
+	}
 
-	dm_spi_bus->max_hz = plat->max_hz;
+	priv->regs = (struct stm32_qspi_regs *)res.start;
 
-	priv->regs = (struct stm32_qspi_regs *)(uintptr_t)plat->base;
+	ret = dev_read_resource_byname(bus, "qspi_mm", &res);
+	if (ret) {
+		dev_err(bus, "can't get mmap base address(ret = %d)!\n", ret);
+		return ret;
+	}
+
+	priv->mm_base = (void __iomem *)res.start;
 
-	priv->max_hz = plat->max_hz;
+	priv->mm_size = resource_size(&res);
+	if (priv->mm_size > STM32_QSPI_MAX_MMAP_SZ)
+		return -EINVAL;
+
+	debug("%s: regs=<0x%p> mapped=<0x%p> mapped_size=<0x%lx>\n",
+	      __func__, priv->regs, priv->mm_base, priv->mm_size);
 
 	ret = clk_get_by_index(bus, 0, &clk);
 	if (ret < 0)
 		return ret;
 
 	ret = clk_enable(&clk);
-
 	if (ret) {
 		dev_err(bus, "failed to enable clock\n");
 		return ret;
@@ -499,78 +380,68 @@
 		reset_deassert(&reset_ctl);
 	}
 
+	priv->cs_used = -1;
+
 	setbits_le32(&priv->regs->cr, STM32_QSPI_CR_SSHIFT);
 
-	return 0;
-}
+	/* Set dcr fsize to max address */
+	setbits_le32(&priv->regs->dcr,
+		     STM32_QSPI_DCR_FSIZE_MASK << STM32_QSPI_DCR_FSIZE_SHIFT);
 
-static int stm32_qspi_remove(struct udevice *bus)
-{
 	return 0;
 }
 
 static int stm32_qspi_claim_bus(struct udevice *dev)
 {
-	struct stm32_qspi_priv *priv;
-	struct udevice *bus;
-	struct spi_flash *flash;
-	struct dm_spi_slave_platdata *slave_plat;
-
-	bus = dev->parent;
-	priv = dev_get_priv(bus);
-	flash = dev_get_uclass_priv(dev);
-	slave_plat = dev_get_parent_platdata(dev);
+	struct stm32_qspi_priv *priv = dev_get_priv(dev->parent);
+	struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
 
-	if (slave_plat->cs >= STM32_MAX_NORCHIP)
+	if (slave_plat->cs >= STM32_QSPI_MAX_CHIP)
 		return -ENODEV;
 
-	_stm32_qspi_set_cs(priv, slave_plat->cs);
+	if (priv->cs_used != slave_plat->cs) {
+		struct stm32_qspi_flash *flash = &priv->flash[slave_plat->cs];
 
-	_stm32_qspi_set_flash_size(priv, flash->size);
+		priv->cs_used = slave_plat->cs;
 
-	_stm32_qspi_enable(priv);
+		if (flash->initialized) {
+			/* Set the configuration: speed + cs */
+			writel(flash->cr, &priv->regs->cr);
+			writel(flash->dcr, &priv->regs->dcr);
+		} else {
+			/* Set chip select */
+			clrsetbits_le32(&priv->regs->cr, STM32_QSPI_CR_FSEL,
+					priv->cs_used ? STM32_QSPI_CR_FSEL : 0);
 
-	return 0;
-}
+			/* Save the configuration: speed + cs */
+			flash->cr = readl(&priv->regs->cr);
+			flash->dcr = readl(&priv->regs->dcr);
 
-static int stm32_qspi_release_bus(struct udevice *dev)
-{
-	struct stm32_qspi_priv *priv;
-	struct udevice *bus;
-
-	bus = dev->parent;
-	priv = dev_get_priv(bus);
+			flash->initialized = true;
+		}
+	}
 
-	_stm32_qspi_disable(priv);
+	setbits_le32(&priv->regs->cr, STM32_QSPI_CR_EN);
 
 	return 0;
 }
 
-static int stm32_qspi_xfer(struct udevice *dev, unsigned int bitlen,
-			   const void *dout, void *din, unsigned long flags)
+static int stm32_qspi_release_bus(struct udevice *dev)
 {
-	struct stm32_qspi_priv *priv;
-	struct udevice *bus;
-	struct spi_flash *flash;
+	struct stm32_qspi_priv *priv = dev_get_priv(dev->parent);
 
-	bus = dev->parent;
-	priv = dev_get_priv(bus);
-	flash = dev_get_uclass_priv(dev);
+	clrbits_le32(&priv->regs->cr, STM32_QSPI_CR_EN);
 
-	return _stm32_qspi_xfer(priv, flash, bitlen, (const u8 *)dout,
-				(u8 *)din, flags);
+	return 0;
 }
 
 static int stm32_qspi_set_speed(struct udevice *bus, uint speed)
 {
-	struct stm32_qspi_platdata *plat = bus->platdata;
 	struct stm32_qspi_priv *priv = dev_get_priv(bus);
 	u32 qspi_clk = priv->clock_rate;
 	u32 prescaler = 255;
 	u32 csht;
-
-	if (speed > plat->max_hz)
-		speed = plat->max_hz;
+	int ret;
 
 	if (speed > 0) {
 		prescaler = DIV_ROUND_UP(qspi_clk, speed) - 1;
@@ -583,7 +454,9 @@
 	csht = DIV_ROUND_UP((5 * qspi_clk) / (prescaler + 1), 100000000);
 	csht = (csht - 1) & STM32_QSPI_DCR_CSHT_MASK;
 
-	_stm32_qspi_wait_for_not_busy(priv);
+	ret = _stm32_qspi_wait_for_not_busy(priv);
+	if (ret)
+		return ret;
 
 	clrsetbits_le32(&priv->regs->cr,
 			STM32_QSPI_CR_PRESCALER_MASK <<
@@ -603,8 +476,11 @@
 static int stm32_qspi_set_mode(struct udevice *bus, uint mode)
 {
 	struct stm32_qspi_priv *priv = dev_get_priv(bus);
+	int ret;
 
-	_stm32_qspi_wait_for_not_busy(priv);
+	ret = _stm32_qspi_wait_for_not_busy(priv);
+	if (ret)
+		return ret;
 
 	if ((mode & SPI_CPHA) && (mode & SPI_CPOL))
 		setbits_le32(&priv->regs->dcr, STM32_QSPI_DCR_CKMODE);
@@ -616,20 +492,6 @@
 	if (mode & SPI_CS_HIGH)
 		return -ENODEV;
 
-	if (mode & SPI_RX_QUAD)
-		priv->mode |= SPI_RX_QUAD;
-	else if (mode & SPI_RX_DUAL)
-		priv->mode |= SPI_RX_DUAL;
-	else
-		priv->mode &= ~(SPI_RX_QUAD | SPI_RX_DUAL);
-
-	if (mode & SPI_TX_QUAD)
-		priv->mode |= SPI_TX_QUAD;
-	else if (mode & SPI_TX_DUAL)
-		priv->mode |= SPI_TX_DUAL;
-	else
-		priv->mode &= ~(SPI_TX_QUAD | SPI_TX_DUAL);
-
 	debug("%s: regs=%p, mode=%d rx: ", __func__, priv->regs, mode);
 
 	if (mode & SPI_RX_QUAD)
@@ -649,12 +511,16 @@
 	return 0;
 }
 
+static const struct spi_controller_mem_ops stm32_qspi_mem_ops = {
+	.exec_op = stm32_qspi_exec_op,
+};
+
 static const struct dm_spi_ops stm32_qspi_ops = {
 	.claim_bus	= stm32_qspi_claim_bus,
 	.release_bus	= stm32_qspi_release_bus,
-	.xfer		= stm32_qspi_xfer,
 	.set_speed	= stm32_qspi_set_speed,
 	.set_mode	= stm32_qspi_set_mode,
+	.mem_ops	= &stm32_qspi_mem_ops,
 };
 
 static const struct udevice_id stm32_qspi_ids[] = {
@@ -664,13 +530,10 @@
 };
 
 U_BOOT_DRIVER(stm32_qspi) = {
-	.name	= "stm32_qspi",
-	.id	= UCLASS_SPI,
+	.name = "stm32_qspi",
+	.id = UCLASS_SPI,
 	.of_match = stm32_qspi_ids,
-	.ops	= &stm32_qspi_ops,
-	.ofdata_to_platdata = stm32_qspi_ofdata_to_platdata,
-	.platdata_auto_alloc_size = sizeof(struct stm32_qspi_platdata),
+	.ops = &stm32_qspi_ops,
 	.priv_auto_alloc_size = sizeof(struct stm32_qspi_priv),
-	.probe	= stm32_qspi_probe,
-	.remove = stm32_qspi_remove,
+	.probe = stm32_qspi_probe,
 };
diff --git a/drivers/sysreset/sysreset_syscon.c b/drivers/sysreset/sysreset_syscon.c
index 3450640..3fb39b9 100644
--- a/drivers/sysreset/sysreset_syscon.c
+++ b/drivers/sysreset/sysreset_syscon.c
@@ -36,20 +36,9 @@
 int syscon_reboot_probe(struct udevice *dev)
 {
 	struct syscon_reboot_priv *priv = dev_get_priv(dev);
-	int err;
-	u32 phandle;
-	ofnode node;
-
-	err = ofnode_read_u32(dev_ofnode(dev), "regmap", &phandle);
-	if (err)
-		return err;
-
-	node = ofnode_get_by_phandle(phandle);
-	if (!ofnode_valid(node))
-		return -EINVAL;
 
-	priv->regmap = syscon_node_to_regmap(node);
-	if (!priv->regmap) {
+	priv->regmap = syscon_regmap_lookup_by_phandle(dev, "regmap");
+	if (IS_ERR(priv->regmap)) {
 		pr_err("unable to find regmap\n");
 		return -ENODEV;
 	}
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 2eac4b6..4341287 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -120,7 +120,7 @@
 
 config SYS_WHITE_ON_BLACK
 	bool "Display console as white on a black background"
-	default y if ARCH_AT91 || ARCH_EXYNOS || ARCH_ROCKCHIP || TEGRA || X86
+	default y if ARCH_AT91 || ARCH_EXYNOS || ARCH_ROCKCHIP || TEGRA || X86 || ARCH_SUNXI
 	help
 	 Normally the display is black on a white background, Enable this
 	 option to invert this, i.e. white on a black background. This can be
diff --git a/drivers/video/console_normal.c b/drivers/video/console_normal.c
index 2cfa510..7f01ee9 100644
--- a/drivers/video/console_normal.c
+++ b/drivers/video/console_normal.c
@@ -84,7 +84,8 @@
 		return -EAGAIN;
 
 	for (row = 0; row < VIDEO_FONT_HEIGHT; row++) {
-		uchar bits = video_fontdata[ch * VIDEO_FONT_HEIGHT + row];
+		unsigned int idx = (u8)ch * VIDEO_FONT_HEIGHT + row;
+		uchar bits = video_fontdata[idx];
 
 		switch (vid_priv->bpix) {
 #ifdef CONFIG_VIDEO_BPP8
diff --git a/drivers/video/console_rotate.c b/drivers/video/console_rotate.c
index f076570..71a5c5e 100644
--- a/drivers/video/console_rotate.c
+++ b/drivers/video/console_rotate.c
@@ -90,7 +90,7 @@
 	int i, col;
 	int mask = 0x80;
 	void *line;
-	uchar *pfont = video_fontdata + ch * VIDEO_FONT_HEIGHT;
+	uchar *pfont = video_fontdata + (u8)ch * VIDEO_FONT_HEIGHT;
 
 	line = vid_priv->fb + (VID_TO_PIXEL(x_frac) + 1) *
 			vid_priv->line_length - (y + 1) * pbytes;
@@ -222,7 +222,8 @@
 			VIDEO_FONT_WIDTH - 1) * VNBYTES(vid_priv->bpix);
 
 	for (row = 0; row < VIDEO_FONT_HEIGHT; row++) {
-		uchar bits = video_fontdata[ch * VIDEO_FONT_HEIGHT + row];
+		unsigned int idx = (u8)ch * VIDEO_FONT_HEIGHT + row;
+		uchar bits = video_fontdata[idx];
 
 		switch (vid_priv->bpix) {
 #ifdef CONFIG_VIDEO_BPP8
@@ -348,7 +349,7 @@
 	void *line = vid_priv->fb +
 		(vid_priv->ysize - VID_TO_PIXEL(x_frac) - 1) *
 		vid_priv->line_length + y * pbytes;
-	uchar *pfont = video_fontdata + ch * VIDEO_FONT_HEIGHT;
+	uchar *pfont = video_fontdata + (u8)ch * VIDEO_FONT_HEIGHT;
 
 	if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac)
 		return -EAGAIN;
diff --git a/drivers/video/pwm_backlight.c b/drivers/video/pwm_backlight.c
index bd733f5..a587977 100644
--- a/drivers/video/pwm_backlight.c
+++ b/drivers/video/pwm_backlight.c
@@ -39,6 +39,12 @@
 	struct udevice *pwm;
 	uint channel;
 	uint period_ns;
+	/*
+	 * the polarity of one PWM
+	 * 0: normal polarity
+	 * 1: inverted polarity
+	 */
+	bool polarity;
 	u32 *levels;
 	int num_levels;
 	uint default_level;
@@ -57,7 +63,10 @@
 		(priv->max_level - priv->min_level + 1);
 	ret = pwm_set_config(priv->pwm, priv->channel, priv->period_ns,
 			     duty_cycle);
+	if (ret)
+		return log_ret(ret);
 
+	ret = pwm_set_invert(priv->pwm, priv->channel, priv->polarity);
 	return log_ret(ret);
 }
 
@@ -202,6 +211,8 @@
 		return log_msg_ret("Not enough arguments to pwm\n", -EINVAL);
 	priv->channel = args.args[0];
 	priv->period_ns = args.args[1];
+	if (args.args_count > 2)
+		priv->polarity = args.args[2];
 
 	index = dev_read_u32_default(dev, "default-brightness-level", 255);
 	cell = dev_read_prop(dev, "brightness-levels", &len);
diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c
index 2ca19d4..c31303b 100644
--- a/drivers/video/vidconsole-uclass.c
+++ b/drivers/video/vidconsole-uclass.c
@@ -259,6 +259,43 @@
 	priv->escape = 0;
 
 	switch (ch) {
+	case 'A':
+	case 'B':
+	case 'C':
+	case 'D':
+	case 'E':
+	case 'F': {
+		int row, col, num;
+		char *s = priv->escape_buf;
+
+		/*
+		 * Cursor up/down: [%dA, [%dB, [%dE, [%dF
+		 * Cursor left/right: [%dD, [%dC
+		 */
+		s++;    /* [ */
+		s = parsenum(s, &num);
+		if (num == 0)			/* No digit in sequence ... */
+			num = 1;		/* ... means "move by 1". */
+
+		get_cursor_position(priv, &row, &col);
+		if (ch == 'A' || ch == 'F')
+			row -= num;
+		if (ch == 'C')
+			col += num;
+		if (ch == 'D')
+			col -= num;
+		if (ch == 'B' || ch == 'E')
+			row += num;
+		if (ch == 'E' || ch == 'F')
+			col = 0;
+		if (col < 0)
+			col = 0;
+		if (row < 0)
+			row = 0;
+		/* Right and bottom overflows are handled in the callee. */
+		set_cursor_position(priv, row, col);
+		break;
+	}
 	case 'H':
 	case 'f': {
 		int row, col;
@@ -309,6 +346,25 @@
 		}
 		break;
 	}
+	case 'K': {
+		struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
+		int mode;
+
+		/*
+		 * Clear (parts of) current line
+		 *   [0K       - clear line to end
+		 *   [2K       - clear entire line
+		 */
+		parsenum(priv->escape_buf + 1, &mode);
+
+		if (mode == 2) {
+			int row, col;
+
+			get_cursor_position(priv, &row, &col);
+			vidconsole_set_row(dev, row, vid_priv->colour_bg);
+		}
+		break;
+	}
 	case 'm': {
 		struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
 		char *s = priv->escape_buf;
@@ -360,6 +416,13 @@
 				vid_priv->colour_fg = vid_console_color(
 						vid_priv, vid_priv->fg_col_idx);
 				break;
+			case 7:
+				/* reverse video */
+				vid_priv->colour_fg = vid_console_color(
+						vid_priv, vid_priv->bg_col_idx);
+				vid_priv->colour_bg = vid_console_color(
+						vid_priv, vid_priv->fg_col_idx);
+				break;
 			case 30 ... 37:
 				/* foreground color */
 				vid_priv->fg_col_idx &= ~7;
@@ -368,9 +431,11 @@
 						vid_priv, vid_priv->fg_col_idx);
 				break;
 			case 40 ... 47:
-				/* background color */
+				/* background color, also mask the bold bit */
+				vid_priv->bg_col_idx &= ~0xf;
+				vid_priv->bg_col_idx |= val - 40;
 				vid_priv->colour_bg = vid_console_color(
-							vid_priv, val - 40);
+						vid_priv, vid_priv->bg_col_idx);
 				break;
 			default:
 				/* ignore unsupported SGR parameter */
@@ -392,6 +457,32 @@
 	priv->escape = 0;
 }
 
+/* Put that actual character on the screen (using the CP437 code page). */
+static int vidconsole_output_glyph(struct udevice *dev, char ch)
+{
+	struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
+	int ret;
+
+	/*
+	 * Failure of this function normally indicates an unsupported
+	 * colour depth. Check this and return an error to help with
+	 * diagnosis.
+	 */
+	ret = vidconsole_putc_xy(dev, priv->xcur_frac, priv->ycur, ch);
+	if (ret == -EAGAIN) {
+		vidconsole_newline(dev);
+		ret = vidconsole_putc_xy(dev, priv->xcur_frac, priv->ycur, ch);
+	}
+	if (ret < 0)
+		return ret;
+	priv->xcur_frac += ret;
+	priv->last_ch = ch;
+	if (priv->xcur_frac >= priv->xsize_frac)
+		vidconsole_newline(dev);
+
+	return 0;
+}
+
 int vidconsole_put_char(struct udevice *dev, char ch)
 {
 	struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
@@ -429,23 +520,9 @@
 		priv->last_ch = 0;
 		break;
 	default:
-		/*
-		 * Failure of this function normally indicates an unsupported
-		 * colour depth. Check this and return an error to help with
-		 * diagnosis.
-		 */
-		ret = vidconsole_putc_xy(dev, priv->xcur_frac, priv->ycur, ch);
-		if (ret == -EAGAIN) {
-			vidconsole_newline(dev);
-			ret = vidconsole_putc_xy(dev, priv->xcur_frac,
-						 priv->ycur, ch);
-		}
+		ret = vidconsole_output_glyph(dev, ch);
 		if (ret < 0)
 			return ret;
-		priv->xcur_frac += ret;
-		priv->last_ch = ch;
-		if (priv->xcur_frac >= priv->xsize_frac)
-			vidconsole_newline(dev);
 		break;
 	}
 
diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c
index f307cf2..14aac88 100644
--- a/drivers/video/video-uclass.c
+++ b/drivers/video/video-uclass.c
@@ -136,6 +136,7 @@
 		back = temp;
 	}
 	priv->fg_col_idx = fore;
+	priv->bg_col_idx = back;
 	priv->colour_fg = vid_console_color(priv, fore);
 	priv->colour_bg = vid_console_color(priv, back);
 }
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 34e78be..9d7f503 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -97,6 +97,7 @@
 config WDT_ORION
 	bool "Orion watchdog timer support"
 	depends on WDT
+	select CLK
 	help
 	   Select this to enable Orion watchdog timer, which can be found on some
 	   Marvell Armada chips.
diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c
index a0df02d..885821d 100644
--- a/drivers/watchdog/orion_wdt.c
+++ b/drivers/watchdog/orion_wdt.c
@@ -14,7 +14,9 @@
 
 #include <common.h>
 #include <dm.h>
+#include <clk.h>
 #include <wdt.h>
+#include <linux/kernel.h>
 #include <asm/io.h>
 #include <asm/arch/cpu.h>
 #include <asm/arch/soc.h>
@@ -27,6 +29,8 @@
 	void __iomem *rstout;
 	void __iomem *rstout_mask;
 	u32 timeout;
+	unsigned long clk_rate;
+	struct clk clk;
 };
 
 #define RSTOUT_ENABLE_BIT		BIT(8)
@@ -44,17 +48,18 @@
 	struct orion_wdt_priv *priv = dev_get_priv(dev);
 
 	/* Reload watchdog duration */
-	writel(priv->timeout, priv->reg + priv->wdt_counter_offset);
+	writel(priv->clk_rate * priv->timeout,
+	       priv->reg + priv->wdt_counter_offset);
 
 	return 0;
 }
 
-static int orion_wdt_start(struct udevice *dev, u64 timeout, ulong flags)
+static int orion_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags)
 {
 	struct orion_wdt_priv *priv = dev_get_priv(dev);
 	u32 reg;
 
-	priv->timeout = (u32) timeout;
+	priv->timeout = DIV_ROUND_UP(timeout_ms, 1000);
 
 	/* Enable the fixed watchdog clock input */
 	reg = readl(priv->reg + TIMER_CTRL);
@@ -62,7 +67,8 @@
 	writel(reg, priv->reg + TIMER_CTRL);
 
 	/* Set watchdog duration */
-	writel(priv->timeout, priv->reg + priv->wdt_counter_offset);
+	writel(priv->clk_rate * priv->timeout,
+	       priv->reg + priv->wdt_counter_offset);
 
 	/* Clear the watchdog expiration bit */
 	reg = readl(priv->reg + TIMER_A370_STATUS);
@@ -114,9 +120,7 @@
 	fdt_addr_t addr;
 	fdt_size_t off;
 
-	addr = fdtdec_get_addr_size_auto_noparent(
-		gd->fdt_blob, dev_of_offset(dev), "reg", index, &off, true);
-
+	addr = devfdt_get_addr_size_index(dev, index, &off);
 	if (addr == FDT_ADDR_T_NONE)
 		return false;
 
@@ -149,9 +153,18 @@
 
 static int orion_wdt_probe(struct udevice *dev)
 {
+	struct orion_wdt_priv *priv = dev_get_priv(dev);
+	int ret;
+
 	debug("%s: Probing wdt%u\n", __func__, dev->seq);
 	orion_wdt_stop(dev);
 
+	ret = clk_get_by_name(dev, "fixed", &priv->clk);
+	if (!ret)
+		priv->clk_rate = clk_get_rate(&priv->clk);
+	else
+		priv->clk_rate = 25000000;
+
 	return 0;
 }
 
diff --git a/dts/Kconfig b/dts/Kconfig
index a5f30c8..c9ab66c 100644
--- a/dts/Kconfig
+++ b/dts/Kconfig
@@ -291,10 +291,10 @@
 config OF_SPL_REMOVE_PROPS
 	string "List of device tree properties to drop for SPL"
 	depends on SPL_OF_CONTROL
-	default "interrupt-parent" if SPL_PINCTRL && SPL_CLK
-	default "clocks clock-names interrupt-parent" if SPL_PINCTRL
-	default "pinctrl-0 pinctrl-names interrupt-parent" if SPL_CLK
-	default "pinctrl-0 pinctrl-names clocks clock-names interrupt-parent"
+	default "interrupt-parent interrupts" if SPL_PINCTRL && SPL_CLK
+	default "clocks clock-names interrupt-parent interrupts" if SPL_PINCTRL
+	default "pinctrl-0 pinctrl-names interrupt-parent interrupts" if SPL_CLK
+	default "pinctrl-0 pinctrl-names clocks clock-names interrupt-parent interrupts"
 	help
 	  Since SPL normally runs in a reduced memory space, the device tree
 	  is cut down to only what is needed to load and start U-Boot. Only
diff --git a/include/configs/ap152.h b/include/configs/ap152.h
new file mode 100644
index 0000000..c948a44
--- /dev/null
+++ b/include/configs/ap152.h
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2018 Rosy Song <rosysong@rosinson.com>
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#define CONFIG_SYS_HZ                   1000
+#define CONFIG_SYS_MHZ                  375
+#define CONFIG_SYS_MIPS_TIMER_FREQ      (CONFIG_SYS_MHZ * 1000000)
+
+#define CONFIG_SYS_MONITOR_BASE         CONFIG_SYS_TEXT_BASE
+
+#define CONFIG_SYS_MALLOC_LEN           0x40000
+#define CONFIG_SYS_BOOTPARAMS_LEN       0x20000
+
+#define CONFIG_SYS_SDRAM_BASE           0x80000000
+#define CONFIG_SYS_LOAD_ADDR            0x81000000
+
+#define CONFIG_SYS_INIT_RAM_ADDR        0xbd000000
+#define CONFIG_SYS_INIT_RAM_SIZE        0x2000
+#define CONFIG_SYS_INIT_SP_ADDR \
+	(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE - 1)
+
+/*
+ * Serial Port
+ */
+#define CONFIG_SYS_NS16550_CLK          25000000
+#define CONFIG_SYS_BAUDRATE_TABLE \
+	{9600, 19200, 38400, 57600, 115200}
+
+#define CONFIG_BOOTCOMMAND              "sf probe;" \
+					"mtdparts default;" \
+					"bootm 0x9f060000"
+
+#define CONFIG_ENV_SPI_MAX_HZ           25000000
+#define CONFIG_ENV_OFFSET               0x40000
+#define CONFIG_ENV_SECT_SIZE            0x10000
+#define CONFIG_ENV_SIZE                 0x10000
+
+/* Miscellaneous configurable options */
+
+/*
+ * Diagnostics
+ */
+#define CONFIG_SYS_MEMTEST_START        0x80100000
+#define CONFIG_SYS_MEMTEST_END          0x83f00000
+
+#endif  /* __CONFIG_H */
diff --git a/include/configs/clearfog.h b/include/configs/clearfog.h
index c51cf28..9f8d3cc 100644
--- a/include/configs/clearfog.h
+++ b/include/configs/clearfog.h
@@ -21,8 +21,6 @@
  * Commands configuration
  */
 
-/* SPI NOR flash default params, used by sf commands */
-
 /*
  * SDIO/MMC Card Configuration
  */
diff --git a/include/configs/db-88f6720.h b/include/configs/db-88f6720.h
index 55968c2..63194d5 100644
--- a/include/configs/db-88f6720.h
+++ b/include/configs/db-88f6720.h
@@ -32,8 +32,6 @@
 #define CONFIG_EHCI_IS_TDI
 #define CONFIG_USB_MAX_CONTROLLER_COUNT 3
 
-/* SPI NOR flash default params, used by sf commands */
-
 /* Environment in SPI NOR flash */
 #define CONFIG_ENV_OFFSET		(1 << 20) /* 1MiB in */
 #define CONFIG_ENV_SIZE			(64 << 10) /* 64KiB */
diff --git a/include/configs/db-88f6820-amc.h b/include/configs/db-88f6820-amc.h
index f1bdc2d..2fdc845 100644
--- a/include/configs/db-88f6820-amc.h
+++ b/include/configs/db-88f6820-amc.h
@@ -16,8 +16,6 @@
  * Commands configuration
  */
 
-/* SPI NOR flash default params, used by sf commands */
-
 /* USB/EHCI configuration */
 #define CONFIG_EHCI_IS_TDI
 
diff --git a/include/configs/db-88f6820-gp.h b/include/configs/db-88f6820-gp.h
index d378052..ec2405b 100644
--- a/include/configs/db-88f6820-gp.h
+++ b/include/configs/db-88f6820-gp.h
@@ -24,12 +24,6 @@
 #define CONFIG_SYS_I2C_SPEED		100000
 
 /*
- * SPI Flash configuration for the environemnt access
- */
-
-/* SPI NOR flash default params, used by sf commands */
-
-/*
  * SDIO/MMC Card Configuration
  */
 #define CONFIG_SYS_MMC_BASE		MVEBU_SDIO_BASE
diff --git a/include/configs/db-mv784mp-gp.h b/include/configs/db-mv784mp-gp.h
index b78dbcb..1f9d24b 100644
--- a/include/configs/db-mv784mp-gp.h
+++ b/include/configs/db-mv784mp-gp.h
@@ -29,8 +29,6 @@
 #define CONFIG_EHCI_IS_TDI
 #define CONFIG_USB_MAX_CONTROLLER_COUNT 3
 
-/* SPI NOR flash default params, used by sf commands */
-
 /* Environment in SPI NOR flash */
 #define CONFIG_ENV_OFFSET		(1 << 20) /* 1MiB in */
 #define CONFIG_ENV_SIZE			(64 << 10) /* 64KiB */
diff --git a/include/configs/db-xc3-24g4xg.h b/include/configs/db-xc3-24g4xg.h
new file mode 100644
index 0000000..0f75ad7
--- /dev/null
+++ b/include/configs/db-xc3-24g4xg.h
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2014 Stefan Roese <sr@denx.de>
+ */
+
+#ifndef _CONFIG_DB_XC3_24G4G_H
+#define _CONFIG_DB_XC3_24G4G_H
+
+/*
+ * High Level Configuration Options (easy to change)
+ */
+
+#define CONFIG_SYS_KWD_CONFIG	$(CONFIG_BOARDDIR)/kwbimage.cfg
+#define CONFIG_SYS_TCLK		200000000	/* 200MHz */
+
+/* USB/EHCI configuration */
+#define CONFIG_EHCI_IS_TDI
+
+/* Environment in SPI NOR flash */
+#define CONFIG_ENV_OFFSET		(1 << 20) /* 1MiB in */
+#define CONFIG_ENV_SIZE			(64 << 10) /* 64KiB */
+#define CONFIG_ENV_SECT_SIZE		(256 << 10) /* 256KiB sectors */
+
+/* NAND */
+#define CONFIG_SYS_NAND_USE_FLASH_BBT
+#define CONFIG_SYS_NAND_ONFI_DETECTION
+
+/* Keep device tree and initrd in lower memory so the kernel can access them */
+#define CONFIG_EXTRA_ENV_SETTINGS	\
+	"fdt_high=0x10000000\0"		\
+	"initrd_high=0x10000000\0"
+
+/*
+ * mv-common.h should be defined after CMD configs since it used them
+ * to enable certain macros
+ */
+#include "mv-common.h"
+#undef CONFIG_SYS_MAXARGS
+#define CONFIG_SYS_MAXARGS 96
+
+#endif /* _CONFIG_DB_XC3_24G4G_H */
diff --git a/include/configs/ds414.h b/include/configs/ds414.h
index 275a2b4..192c055 100644
--- a/include/configs/ds414.h
+++ b/include/configs/ds414.h
@@ -28,8 +28,6 @@
 #define CONFIG_SYS_I2C_SLAVE		0x0
 #define CONFIG_SYS_I2C_SPEED		100000
 
-/* SPI NOR flash default params, used by sf commands */
-
 /* Environment in SPI NOR flash */
 #define CONFIG_ENV_OFFSET		0x7E0000   /* RedBoot config partition in DTS */
 #define CONFIG_ENV_SIZE			(64 << 10) /* 64KiB */
diff --git a/include/configs/helios4.h b/include/configs/helios4.h
index df4d8bc..b2badab 100644
--- a/include/configs/helios4.h
+++ b/include/configs/helios4.h
@@ -23,8 +23,6 @@
  * Commands configuration
  */
 
-/* SPI NOR flash default params, used by sf commands */
-
 /*
  * SDIO/MMC Card Configuration
  */
diff --git a/include/configs/lsxl.h b/include/configs/lsxl.h
index 72e6265..55c4e63 100644
--- a/include/configs/lsxl.h
+++ b/include/configs/lsxl.h
@@ -76,9 +76,9 @@
 	"kernel_addr=0x00800000\0"					\
 	"ramdisk_addr=0x01000000\0"					\
 	"fdt_addr=0x00ff0000\0"						\
-	"bootcmd_legacy=ide reset "					\
-		"&& load ide ${hdpart} ${kernel_addr} /uImage.buffalo "	\
-		"&& load ide ${hdpart} ${ramdisk_addr} /initrd.buffalo "\
+	"bootcmd_legacy=sata init "					\
+		"&& load sata ${hdpart} ${kernel_addr} /uImage.buffalo "\
+		"&& load sata ${hdpart} ${ramdisk_addr} /initrd.buffalo "\
 		"&& bootm ${kernel_addr} ${ramdisk_addr}\0"		\
 	"bootcmd_net=bootp ${kernel_addr} vmlinuz "			\
 		"&& tftpboot ${ramdisk_addr} initrd.img "		\
@@ -86,11 +86,11 @@
 		"&& tftpboot ${fdt_addr} " CONFIG_FDTFILE " "		\
 		"&& bootz ${kernel_addr} "				\
 			"${ramdisk_addr}:${ramdisk_len} ${fdt_addr}\0"	\
-	"bootcmd_hdd=ide reset "					\
-		"&& load ide ${hdpart} ${kernel_addr} /vmlinuz "	\
-		"&& load ide ${hdpart} ${ramdisk_addr} /initrd.img "	\
+	"bootcmd_hdd=sata init "					\
+		"&& load sata ${hdpart} ${kernel_addr} /vmlinuz "	\
+		"&& load sata ${hdpart} ${ramdisk_addr} /initrd.img "	\
 		"&& setenv ramdisk_len ${filesize} "			\
-		"&& load ide ${hdpart} ${fdt_addr} /dtb "		\
+		"&& load sata ${hdpart} ${fdt_addr} /dtb "		\
 		"&& bootz ${kernel_addr} "				\
 			"${ramdisk_addr}:${ramdisk_len} ${fdt_addr}\0"	\
 	"bootcmd_usb=usb start "					\
@@ -131,13 +131,10 @@
 #undef CONFIG_RESET_PHY_R
 #endif /* CONFIG_CMD_NET */
 
-#ifdef CONFIG_IDE
-#undef CONFIG_SYS_IDE_MAXBUS
-#define CONFIG_SYS_IDE_MAXBUS		1
-#undef CONFIG_SYS_IDE_MAXDEVICE
-#define CONFIG_SYS_IDE_MAXDEVICE	1
-#define CONFIG_SYS_ATA_IDE0_OFFSET	MV_SATA_PORT0_OFFSET
+#ifdef CONFIG_SATA
+#define CONFIG_SYS_SATA_MAX_DEVICE 1
 #define CONFIG_SYS_64BIT_LBA
+#define CONFIG_LBA48
 #endif
 
 #endif /* _CONFIG_LSXL_H */
diff --git a/include/configs/mvebu_armada-8k.h b/include/configs/mvebu_armada-8k.h
index f4972b6..b28f3b9 100644
--- a/include/configs/mvebu_armada-8k.h
+++ b/include/configs/mvebu_armada-8k.h
@@ -49,10 +49,6 @@
 /* End of 16M scrubbed by training in bootrom */
 #define CONFIG_SYS_INIT_SP_ADDR         (CONFIG_SYS_TEXT_BASE + 0xFF0000)
 
-/*
- * SPI Flash configuration
- */
-
 #define CONFIG_ENV_OFFSET		0x180000 /* as Marvell U-Boot version */
 #define CONFIG_ENV_SIZE			(64 << 10) /* 64KiB */
 #define CONFIG_ENV_SECT_SIZE		(64 << 10) /* 64KiB sectors */
diff --git a/include/configs/stm32mp1.h b/include/configs/stm32mp1.h
index 701298c..737dfd6 100644
--- a/include/configs/stm32mp1.h
+++ b/include/configs/stm32mp1.h
@@ -10,17 +10,17 @@
 #include <linux/sizes.h>
 #include <asm/arch/stm32.h>
 
-#define CONFIG_PREBOOT
-
 /*
  * Number of clock ticks in 1 sec
  */
 #define CONFIG_SYS_HZ				1000
 
+#ifndef CONFIG_STM32MP1_TRUSTED
 /* PSCI support */
 #define CONFIG_ARMV7_PSCI_1_0
 #define CONFIG_ARMV7_SECURE_BASE		STM32_SYSRAM_BASE
 #define CONFIG_ARMV7_SECURE_MAX_SIZE		STM32_SYSRAM_SIZE
+#endif
 
 /*
  * malloc() pool size
@@ -53,6 +53,9 @@
 #define CONFIG_SETUP_MEMORY_TAGS
 #define CONFIG_INITRD_TAG
 
+/* Extend size of kernel image for uncompression */
+#define CONFIG_SYS_BOOTM_LEN			SZ_32M
+
 /* SPL support */
 #ifdef CONFIG_SPL
 /* BOOTROM load address */
@@ -69,36 +72,65 @@
 					 STM32_SYSRAM_SIZE)
 #endif /* #ifdef CONFIG_SPL */
 
+#define CONFIG_SYS_MEMTEST_START	STM32_DDR_BASE
+#define CONFIG_SYS_MEMTEST_END		(CONFIG_SYS_MEMTEST_START + SZ_64M)
+#define CONFIG_SYS_MEMTEST_SCRATCH	(CONFIG_SYS_MEMTEST_END + 4)
+
 /*MMC SD*/
 #define CONFIG_SYS_MMC_MAX_DEVICE	3
 #define CONFIG_SUPPORT_EMMC_BOOT
 
-#if !defined(CONFIG_SPL) || !defined(CONFIG_SPL_BUILD)
+/*****************************************************************************/
+#ifdef CONFIG_DISTRO_DEFAULTS
+/*****************************************************************************/
+
+#if !defined(CONFIG_SPL_BUILD)
 
 #define BOOT_TARGET_DEVICES(func) \
 	func(MMC, mmc, 1) \
 	func(MMC, mmc, 0) \
 	func(MMC, mmc, 2)
+/*
+ * bootcmd for stm32mp1:
+ * for serial/usb: execute the stm32prog command
+ * for mmc boot (eMMC, SD card), boot only on the same device
+ * for nand boot, boot with on ubifs partition on nand
+ * for nor boot, use the default order
+ */
+#define CONFIG_PREBOOT
 
-#include <config_distro_bootcmd.h>
+#define STM32MP_BOOTCMD "bootcmd_stm32mp=" \
+	"echo \"Boot over ${boot_device}${boot_instance}!\";" \
+	"if test ${boot_device} = serial || test ${boot_device} = usb;" \
+	"then stm32prog ${boot_device} ${boot_instance}; " \
+	"else " \
+		"if test ${boot_device} = mmc;" \
+		"then env set boot_targets \"mmc${boot_instance}\"; fi;" \
+		"if test ${boot_device} = nand;" \
+		"then env set boot_targets ubifs0; fi;" \
+		"run distro_bootcmd;" \
+	"fi;\0"
 
-#define STM32MP_PREBOOT	\
-	"echo \"Boot over ${boot_device}${boot_instance}!\"; " \
-	"if test \"${boot_device}\" = \"mmc\"; then " \
-		"env set boot_targets \"mmc${boot_instance}\"; "\
-	"fi;"
+#include <config_distro_bootcmd.h>
 
+/*
+ * memory layout for 32M uncompressed/compressed kernel,
+ * 1M fdt, 1M script, 1M pxe and 1M for splashimage
+ * and the ramdisk at the end.
+ */
 #define CONFIG_EXTRA_ENV_SETTINGS \
-	"scriptaddr=0xC0000000\0" \
-	"pxefile_addr_r=0xC0000000\0" \
-	"kernel_addr_r=0xC1000000\0" \
-	"fdt_addr_r=0xC4000000\0" \
-	"ramdisk_addr_r=0xC4100000\0" \
+	"kernel_addr_r=0xc2000000\0" \
+	"fdt_addr_r=0xc4000000\0" \
+	"scriptaddr=0xc4100000\0" \
+	"pxefile_addr_r=0xc4200000\0" \
+	"splashimage=0xc4300000\0"  \
+	"ramdisk_addr_r=0xc4400000\0" \
 	"fdt_high=0xffffffff\0" \
 	"initrd_high=0xffffffff\0" \
-	"preboot=" STM32MP_PREBOOT "\0" \
+	STM32MP_BOOTCMD \
 	BOOTENV
 
 #endif /* ifndef CONFIG_SPL_BUILD */
+#endif /* ifdef CONFIG_DISTRO_DEFAULTS*/
 
 #endif /* __CONFIG_H */
diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h
index b01d1c3..ee18260 100644
--- a/include/configs/sunxi-common.h
+++ b/include/configs/sunxi-common.h
@@ -449,7 +449,6 @@
 	"stdout=serial,vga\0" \
 	"stderr=serial,vga\0"
 #elif CONFIG_DM_VIDEO
-#define CONFIG_SYS_WHITE_ON_BLACK
 #define CONSOLE_STDOUT_SETTINGS \
 	"stdout=serial,vidconsole\0" \
 	"stderr=serial,vidconsole\0"
diff --git a/include/configs/theadorable.h b/include/configs/theadorable.h
index 59b2546..cd92835 100644
--- a/include/configs/theadorable.h
+++ b/include/configs/theadorable.h
@@ -39,8 +39,6 @@
 #define CONFIG_EHCI_IS_TDI
 #define CONFIG_USB_MAX_CONTROLLER_COUNT 3
 
-/* SPI NOR flash default params, used by sf commands */
-
 /* Environment in SPI NOR flash */
 #define CONFIG_ENV_OFFSET		(1 << 20) /* 1MiB in */
 #define CONFIG_ENV_SIZE			(64 << 10) /* 64KiB */
diff --git a/include/configs/turris_mox.h b/include/configs/turris_mox.h
index 5d5394e..0de40ed 100644
--- a/include/configs/turris_mox.h
+++ b/include/configs/turris_mox.h
@@ -63,10 +63,6 @@
 #define CONFIG_I2C_MV
 #define CONFIG_SYS_I2C_SLAVE		0x0
 
-/*
- * SPI Flash configuration
- */
-
 /* Environment in SPI NOR flash */
 #define CONFIG_ENV_OFFSET		0x180000 /* as Marvell U-Boot version */
 #define CONFIG_ENV_SIZE			(64 << 10) /* 64KiB */
diff --git a/include/configs/turris_omnia.h b/include/configs/turris_omnia.h
index 038f639..c7805cf 100644
--- a/include/configs/turris_omnia.h
+++ b/include/configs/turris_omnia.h
@@ -34,9 +34,6 @@
 # define CONFIG_WATCHDOG
 #endif
 
-/* SPI NOR flash default params, used by sf commands */
-#define CONFIG_SPI_FLASH_SPANSION
-
 /*
  * SDIO/MMC Card Configuration
  */
diff --git a/include/configs/vcoreiii.h b/include/configs/vcoreiii.h
index 2840c7b..8c68372 100644
--- a/include/configs/vcoreiii.h
+++ b/include/configs/vcoreiii.h
@@ -10,7 +10,7 @@
 
 /* Onboard devices */
 
-#define CONFIG_SYS_MALLOC_LEN		0x100000
+#define CONFIG_SYS_MALLOC_LEN		0x1F0000
 #define CONFIG_SYS_LOAD_ADDR		0x00100000
 #define CONFIG_SYS_INIT_SP_OFFSET       0x400000
 
@@ -27,7 +27,7 @@
 
 #if defined(CONFIG_ENV_IS_IN_SPI_FLASH) && !defined(CONFIG_ENV_OFFSET)
 #define CONFIG_ENV_OFFSET		(1024 * 1024)
-#define CONFIG_ENV_SIZE			(256 * 1024)
+#define CONFIG_ENV_SIZE			(8 * 1024)
 #define CONFIG_ENV_SECT_SIZE		(256 * 1024)
 
 #define CONFIG_SYS_REDUNDAND_ENVIRONMENT
diff --git a/include/dm/pinctrl.h b/include/dm/pinctrl.h
index ff2b82e..63a7d55 100644
--- a/include/dm/pinctrl.h
+++ b/include/dm/pinctrl.h
@@ -355,18 +355,6 @@
 int pinctrl_decode_pin_config(const void *blob, int node);
 
 /**
- * pinctrl_decode_pin_config_dm() - decode pin configuration flags
- *
- * This decodes some of the PIN_CONFIG values into flags, with each value
- * being (1 << pin_cfg). This does not support things with values like the
- * slew rate.
- *
- * @pinconfig:	Pinconfig udevice
- * @return decoded flag value, or -ve on error
- */
-int pinctrl_decode_pin_config_dm(struct udevice *dev);
-
-/**
  * pinctrl_get_gpio_mux() - get the mux value for a particular GPIO
  *
  * This allows the raw mux value for a GPIO to be obtained. It is
diff --git a/include/dm/util.h b/include/dm/util.h
index 9ff6531..60d3b93 100644
--- a/include/dm/util.h
+++ b/include/dm/util.h
@@ -40,32 +40,6 @@
 #endif
 
 /**
- * Check if a dt node should be or was bound before relocation.
- *
- * Devicetree nodes can be marked as needed to be bound
- * in the loader stages via special devicetree properties.
- *
- * Before relocation this function can be used to check if nodes
- * are required in either SPL or TPL stages.
- *
- * After relocation and jumping into the real U-Boot binary
- * it is possible to determine if a node was bound in one of
- * SPL/TPL stages.
- *
- * There are 3 settings currently in use
- * -
- * - u-boot,dm-pre-reloc: legacy and indicates any of TPL or SPL
- *   Existing platforms only use it to indicate nodes needed in
- *   SPL. Should probably be replaced by u-boot,dm-spl for
- *   existing platforms.
- * @blob: devicetree
- * @offset: node offset
- *
- * Returns true if node is needed in SPL/TL, false otherwise.
- */
-bool dm_fdt_pre_reloc(const void *blob, int offset);
-
-/**
  * Check if an of node should be or was bound before relocation.
  *
  * Devicetree nodes can be marked as needed to be bound
diff --git a/include/dt-bindings/mfd/st,stpmic1.h b/include/dt-bindings/mfd/st,stpmic1.h
new file mode 100644
index 0000000..b2d6c83
--- /dev/null
+++ b/include/dt-bindings/mfd/st,stpmic1.h
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) STMicroelectronics 2018 - All Rights Reserved
+ * Author: Philippe Peurichard <philippe.peurichard@st.com>,
+ * Pascal Paillet <p.paillet@st.com> for STMicroelectronics.
+ */
+
+#ifndef __DT_BINDINGS_STPMIC1_H__
+#define __DT_BINDINGS_STPMIC1_H__
+
+/* IRQ definitions */
+#define IT_PONKEY_F	0
+#define IT_PONKEY_R	1
+#define IT_WAKEUP_F	2
+#define IT_WAKEUP_R	3
+#define IT_VBUS_OTG_F	4
+#define IT_VBUS_OTG_R	5
+#define IT_SWOUT_F	6
+#define IT_SWOUT_R	7
+
+#define IT_CURLIM_BUCK1	8
+#define IT_CURLIM_BUCK2	9
+#define IT_CURLIM_BUCK3	10
+#define IT_CURLIM_BUCK4	11
+#define IT_OCP_OTG	12
+#define IT_OCP_SWOUT	13
+#define IT_OCP_BOOST	14
+#define IT_OVP_BOOST	15
+
+#define IT_CURLIM_LDO1	16
+#define IT_CURLIM_LDO2	17
+#define IT_CURLIM_LDO3	18
+#define IT_CURLIM_LDO4	19
+#define IT_CURLIM_LDO5	20
+#define IT_CURLIM_LDO6	21
+#define IT_SHORT_SWOTG	22
+#define IT_SHORT_SWOUT	23
+
+#define IT_TWARN_F	24
+#define IT_TWARN_R	25
+#define IT_VINLOW_F	26
+#define IT_VINLOW_R	27
+#define IT_SWIN_F	30
+#define IT_SWIN_R	31
+
+#endif /* __DT_BINDINGS_STPMIC1_H__ */
diff --git a/include/dt-bindings/mfd/st,stpmu1.h b/include/dt-bindings/mfd/st,stpmu1.h
deleted file mode 100644
index 81982eb..0000000
--- a/include/dt-bindings/mfd/st,stpmu1.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * This file is part of stpmu1 pmic driver
- *
- * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
- * Author: Pascal Paillet <p.paillet@st.com> for STMicroelectronics.
- *
- * License type: GPLv2
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __DT_BINDINGS_STPMU1_H__
-#define __DT_BINDINGS_STPMU1_H__
-
-/* IRQ definitions */
-#define IT_PONKEY_F 0
-#define IT_PONKEY_R 1
-#define IT_WAKEUP_F 2
-#define IT_WAKEUP_R 3
-#define IT_VBUS_OTG_F 4
-#define IT_VBUS_OTG_R 5
-#define IT_SWOUT_F 6
-#define IT_SWOUT_R 7
-
-#define IT_CURLIM_BUCK1 8
-#define IT_CURLIM_BUCK2 9
-#define IT_CURLIM_BUCK3 10
-#define IT_CURLIM_BUCK4 11
-#define IT_OCP_OTG 12
-#define IT_OCP_SWOUT 13
-#define IT_OCP_BOOST 14
-#define IT_OVP_BOOST 15
-
-#define IT_CURLIM_LDO1 16
-#define IT_CURLIM_LDO2 17
-#define IT_CURLIM_LDO3 18
-#define IT_CURLIM_LDO4 19
-#define IT_CURLIM_LDO5 20
-#define IT_CURLIM_LDO6 21
-#define IT_SHORT_SWOTG 22
-#define IT_SHORT_SWOUT 23
-
-#define IT_TWARN_F 24
-#define IT_TWARN_R 25
-#define IT_VINLOW_F 26
-#define IT_VINLOW_R 27
-#define IT_SWIN_F 30
-#define IT_SWIN_R 31
-
-#endif /* __DT_BINDINGS_STPMU1_H__ */
diff --git a/include/dt-bindings/mscc/jr2_data.h b/include/dt-bindings/mscc/jr2_data.h
new file mode 100644
index 0000000..2f06fc5
--- /dev/null
+++ b/include/dt-bindings/mscc/jr2_data.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/*
+ * Copyright (c) 2018 Microsemi Corporation
+ */
+
+#ifndef _JR2_DATA_H_
+#define _JR2_DATA_H_
+
+#define SERDES1G(x)     (x)
+#define SERDES1G_MAX    SERDES1G(10)
+#define SERDES6G(x)     (SERDES1G_MAX + 1 + (x))
+#define SERDES6G_MAX    SERDES6G(17)
+#define SERDES_MAX      (SERDES6G_MAX + 1)
+
+/* similar with phy_interface_t */
+#define PHY_MODE_SGMII  2
+#define PHY_MODE_QSGMII 4
+
+#endif
diff --git a/include/fdtdec.h b/include/fdtdec.h
index ad00f79..266c582 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -23,15 +23,44 @@
  */
 typedef phys_addr_t fdt_addr_t;
 typedef phys_size_t fdt_size_t;
+
+static inline fdt32_t fdt_addr_unpack(fdt_addr_t addr, fdt32_t *upper)
+{
+	if (upper)
+#ifdef CONFIG_PHYS_64BIT
+		*upper = addr >> 32;
+#else
+		*upper = 0;
+#endif
+
+	return addr;
+}
+
+static inline fdt32_t fdt_size_unpack(fdt_size_t size, fdt32_t *upper)
+{
+	if (upper)
+#ifdef CONFIG_PHYS_64BIT
+		*upper = size >> 32;
+#else
+		*upper = 0;
+#endif
+
+	return size;
+}
+
 #ifdef CONFIG_PHYS_64BIT
 #define FDT_ADDR_T_NONE (-1U)
 #define fdt_addr_to_cpu(reg) be64_to_cpu(reg)
 #define fdt_size_to_cpu(reg) be64_to_cpu(reg)
+#define cpu_to_fdt_addr(reg) cpu_to_be64(reg)
+#define cpu_to_fdt_size(reg) cpu_to_be64(reg)
 typedef fdt64_t fdt_val_t;
 #else
 #define FDT_ADDR_T_NONE (-1U)
 #define fdt_addr_to_cpu(reg) be32_to_cpu(reg)
 #define fdt_size_to_cpu(reg) be32_to_cpu(reg)
+#define cpu_to_fdt_addr(reg) cpu_to_be32(reg)
+#define cpu_to_fdt_size(reg) cpu_to_be32(reg)
 typedef fdt32_t fdt_val_t;
 #endif
 
@@ -992,6 +1021,146 @@
 int fdtdec_setup_memory_banksize(void);
 
 /**
+ * fdtdec_set_phandle() - sets the phandle of a given node
+ *
+ * @param blob		FDT blob
+ * @param node		offset in the FDT blob of the node whose phandle is to
+ *			be set
+ * @param phandle	phandle to set for the given node
+ * @return 0 on success or a negative error code on failure
+ */
+int fdtdec_set_phandle(void *blob, int node, uint32_t phandle);
+
+/**
+ * fdtdec_add_reserved_memory() - add or find a reserved-memory node
+ *
+ * If a reserved-memory node already exists for the given carveout, a phandle
+ * for that node will be returned. Otherwise a new node will be created and a
+ * phandle corresponding to it will be returned.
+ *
+ * See Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt
+ * for details on how to use reserved memory regions.
+ *
+ * As an example, consider the following code snippet:
+ *
+ *     struct fdt_memory fb = {
+ *         .start = 0x92cb3000,
+ *         .end = 0x934b2fff,
+ *     };
+ *     uint32_t phandle;
+ *
+ *     fdtdec_add_reserved_memory(fdt, "framebuffer", &fb, &phandle);
+ *
+ * This results in the following subnode being added to the top-level
+ * /reserved-memory node:
+ *
+ *     reserved-memory {
+ *         #address-cells = <0x00000002>;
+ *         #size-cells = <0x00000002>;
+ *         ranges;
+ *
+ *         framebuffer@92cb3000 {
+ *             reg = <0x00000000 0x92cb3000 0x00000000 0x00800000>;
+ *             phandle = <0x0000004d>;
+ *         };
+ *     };
+ *
+ * If the top-level /reserved-memory node does not exist, it will be created.
+ * The phandle returned from the function call can be used to reference this
+ * reserved memory region from other nodes.
+ *
+ * See fdtdec_set_carveout() for a more elaborate example.
+ *
+ * @param blob		FDT blob
+ * @param basename	base name of the node to create
+ * @param carveout	information about the carveout region
+ * @param phandlep	return location for the phandle of the carveout region
+ * @return 0 on success or a negative error code on failure
+ */
+int fdtdec_add_reserved_memory(void *blob, const char *basename,
+			       const struct fdt_memory *carveout,
+			       uint32_t *phandlep);
+
+/**
+ * fdtdec_get_carveout() - reads a carveout from an FDT
+ *
+ * Reads information about a carveout region from an FDT. The carveout is a
+ * referenced by its phandle that is read from a given property in a given
+ * node.
+ *
+ * @param blob		FDT blob
+ * @param node		name of a node
+ * @param name		name of the property in the given node that contains
+ *			the phandle for the carveout
+ * @param index		index of the phandle for which to read the carveout
+ * @param carveout	return location for the carveout information
+ * @return 0 on success or a negative error code on failure
+ */
+int fdtdec_get_carveout(const void *blob, const char *node, const char *name,
+			unsigned int index, struct fdt_memory *carveout);
+
+/**
+ * fdtdec_set_carveout() - sets a carveout region for a given node
+ *
+ * Sets a carveout region for a given node. If a reserved-memory node already
+ * exists for the carveout, the phandle for that node will be reused. If no
+ * such node exists, a new one will be created and a phandle to it stored in
+ * a specified property of the given node.
+ *
+ * As an example, consider the following code snippet:
+ *
+ *     const char *node = "/host1x@50000000/dc@54240000";
+ *     struct fdt_memory fb = {
+ *         .start = 0x92cb3000,
+ *         .end = 0x934b2fff,
+ *     };
+ *
+ *     fdtdec_set_carveout(fdt, node, "memory-region", 0, "framebuffer", &fb);
+ *
+ * dc@54200000 is a display controller and was set up by the bootloader to
+ * scan out the framebuffer specified by "fb". This would cause the following
+ * reserved memory region to be added:
+ *
+ *     reserved-memory {
+ *         #address-cells = <0x00000002>;
+ *         #size-cells = <0x00000002>;
+ *         ranges;
+ *
+ *         framebuffer@92cb3000 {
+ *             reg = <0x00000000 0x92cb3000 0x00000000 0x00800000>;
+ *             phandle = <0x0000004d>;
+ *         };
+ *     };
+ *
+ * A "memory-region" property will also be added to the node referenced by the
+ * offset parameter.
+ *
+ *     host1x@50000000 {
+ *         ...
+ *
+ *         dc@54240000 {
+ *             ...
+ *             memory-region = <0x0000004d>;
+ *             ...
+ *         };
+ *
+ *         ...
+ *     };
+ *
+ * @param blob		FDT blob
+ * @param node		name of the node to add the carveout to
+ * @param prop_name	name of the property in which to store the phandle of
+ *			the carveout
+ * @param index		index of the phandle to store
+ * @param name		base name of the reserved-memory node to create
+ * @param carveout	information about the carveout to add
+ * @return 0 on success or a negative error code on failure
+ */
+int fdtdec_set_carveout(void *blob, const char *node, const char *prop_name,
+			unsigned int index, const char *name,
+			const struct fdt_memory *carveout);
+
+/**
  * Set up the device tree ready for use
  */
 int fdtdec_setup(void);
diff --git a/include/i2c.h b/include/i2c.h
index ccffc19..a5c760c 100644
--- a/include/i2c.h
+++ b/include/i2c.h
@@ -68,9 +68,11 @@
  * I2C bus udevice.
  *
  * @speed_hz: Bus speed in hertz (typically 100000)
+ * @max_transaction_bytes: Maximal size of single I2C transfer
  */
 struct dm_i2c_bus {
 	int speed_hz;
+	int max_transaction_bytes;
 };
 
 /*
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index cd1f557..e3549f0 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -392,7 +392,7 @@
 	mtd->ooblayout = ooblayout;
 }
 
-static inline int mtd_oobavail(struct mtd_info *mtd, struct mtd_oob_ops *ops)
+static inline u32 mtd_oobavail(struct mtd_info *mtd, struct mtd_oob_ops *ops)
 {
 	return ops->mode == MTD_OPS_AUTO_OOB ? mtd->oobavail : mtd->oobsize;
 }
diff --git a/include/power/stpmic1.h b/include/power/stpmic1.h
new file mode 100644
index 0000000..0e6721d
--- /dev/null
+++ b/include/power/stpmic1.h
@@ -0,0 +1,117 @@
+/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */
+/*
+ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+ */
+
+#ifndef __PMIC_STPMIC1_H_
+#define __PMIC_STPMIC1_H_
+
+#define STPMIC1_MAIN_CR			0x10
+#define STPMIC1_BUCKS_MRST_CR		0x18
+#define STPMIC1_LDOS_MRST_CR		0x1a
+#define STPMIC1_BUCKX_MAIN_CR(buck)	(0x20 + (buck))
+#define STPMIC1_REFDDR_MAIN_CR		0x24
+#define STPMIC1_LDOX_MAIN_CR(ldo)	(0x25 + (ldo))
+#define STPMIC1_BST_SW_CR		0x40
+#define STPMIC1_NVM_SR			0xb8
+#define STPMIC1_NVM_CR			0xb9
+
+/* Main PMIC Control Register (MAIN_CR) */
+#define STPMIC1_SWOFF			BIT(0)
+#define STPMIC1_RREQ_EN			BIT(1)
+
+/* BUCKS_MRST_CR */
+#define STPMIC1_MRST_BUCK(buck)		BIT(buck)
+#define STPMIC1_MRST_BUCK_ALL		GENMASK(3, 0)
+
+/* LDOS_MRST_CR */
+#define STPMIC1_MRST_LDO(ldo)		BIT(ldo)
+#define STPMIC1_MRST_LDO_ALL		GENMASK(6, 0)
+
+/* BUCKx_MAIN_CR (x=1...4) */
+#define STPMIC1_BUCK_ENA		BIT(0)
+#define STPMIC1_BUCK_PREG_MODE		BIT(1)
+#define STPMIC1_BUCK_VOUT_MASK		GENMASK(7, 2)
+#define STPMIC1_BUCK_VOUT_SHIFT		2
+#define STPMIC1_BUCK_VOUT(sel)		(sel << STPMIC1_BUCK_VOUT_SHIFT)
+
+#define STPMIC1_BUCK2_1200000V		STPMIC1_BUCK_VOUT(24)
+#define STPMIC1_BUCK2_1350000V		STPMIC1_BUCK_VOUT(30)
+
+#define STPMIC1_BUCK3_1800000V		STPMIC1_BUCK_VOUT(39)
+
+/* REFDDR_MAIN_CR */
+#define STPMIC1_VREF_ENA		BIT(0)
+
+/* LDOX_MAIN_CR */
+#define STPMIC1_LDO_ENA			BIT(0)
+#define STPMIC1_LDO12356_VOUT_MASK	GENMASK(6, 2)
+#define STPMIC1_LDO12356_VOUT_SHIFT	2
+#define STPMIC1_LDO_VOUT(sel)		(sel << STPMIC1_LDO12356_VOUT_SHIFT)
+
+#define STPMIC1_LDO3_MODE		BIT(7)
+#define STPMIC1_LDO3_DDR_SEL		31
+#define STPMIC1_LDO3_1800000		STPMIC1_LDO_VOUT(9)
+
+#define STPMIC1_LDO4_UV			3300000
+
+/* BST_SW_CR */
+#define STPMIC1_BST_ON			BIT(0)
+#define STPMIC1_VBUSOTG_ON		BIT(1)
+#define STPMIC1_SWOUT_ON		BIT(2)
+#define STPMIC1_PWR_SW_ON		(STPMIC1_VBUSOTG_ON | STPMIC1_SWOUT_ON)
+
+/* NVM_SR */
+#define STPMIC1_NVM_BUSY		BIT(0)
+
+/* NVM_CR */
+#define STPMIC1_NVM_CMD_PROGRAM		1
+#define STPMIC1_NVM_CMD_READ		2
+
+/* Timeout */
+#define STPMIC1_DEFAULT_START_UP_DELAY_MS	1
+#define STPMIC1_DEFAULT_STOP_DELAY_MS		5
+#define STPMIC1_USB_BOOST_START_UP_DELAY_MS	10
+
+enum {
+	STPMIC1_BUCK1,
+	STPMIC1_BUCK2,
+	STPMIC1_BUCK3,
+	STPMIC1_BUCK4,
+	STPMIC1_MAX_BUCK,
+};
+
+enum {
+	STPMIC1_PREG_MODE_HP,
+	STPMIC1_PREG_MODE_LP,
+};
+
+enum {
+	STPMIC1_LDO1,
+	STPMIC1_LDO2,
+	STPMIC1_LDO3,
+	STPMIC1_LDO4,
+	STPMIC1_LDO5,
+	STPMIC1_LDO6,
+	STPMIC1_MAX_LDO,
+};
+
+enum {
+	STPMIC1_LDO_MODE_NORMAL,
+	STPMIC1_LDO_MODE_BYPASS,
+	STPMIC1_LDO_MODE_SINK_SOURCE,
+};
+
+enum {
+	STPMIC1_PWR_SW1,
+	STPMIC1_PWR_SW2,
+	STPMIC1_MAX_PWR_SW,
+};
+
+int stpmic1_shadow_read_byte(u8 addr, u8 *buf);
+int stpmic1_shadow_write_byte(u8 addr, u8 *buf);
+int stpmic1_nvm_read_byte(u8 addr, u8 *buf);
+int stpmic1_nvm_write_byte(u8 addr, u8 *buf);
+int stpmic1_nvm_read_all(u8 *buf, int buf_len);
+int stpmic1_nvm_write_all(u8 *buf, int buf_len);
+#endif
diff --git a/include/power/stpmu1.h b/include/power/stpmu1.h
deleted file mode 100644
index 5906fbf..0000000
--- a/include/power/stpmu1.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */
-/*
- * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
- */
-
-#ifndef __PMIC_STPMU1_H_
-#define __PMIC_STPMU1_H_
-
-#define STPMU1_MASK_RESET_BUCK		0x18
-#define STPMU1_BUCKX_CTRL_REG(buck)	(0x20 + (buck))
-#define STPMU1_VREF_CTRL_REG		0x24
-#define STPMU1_LDOX_CTRL_REG(ldo)	(0x25 + (ldo))
-#define STPMU1_USB_CTRL_REG		0x40
-#define STPMU1_NVM_USER_STATUS_REG	0xb8
-#define STPMU1_NVM_USER_CONTROL_REG	0xb9
-
-#define STPMU1_MASK_RESET_BUCK3		BIT(2)
-
-#define STPMU1_BUCK_EN			BIT(0)
-#define STPMU1_BUCK_MODE		BIT(1)
-#define STPMU1_BUCK_OUTPUT_MASK		GENMASK(7, 2)
-#define STPMU1_BUCK_OUTPUT_SHIFT	2
-#define STPMU1_BUCK2_1200000V		(24 << STPMU1_BUCK_OUTPUT_SHIFT)
-#define STPMU1_BUCK2_1350000V		(30 << STPMU1_BUCK_OUTPUT_SHIFT)
-#define STPMU1_BUCK3_1800000V		(39 << STPMU1_BUCK_OUTPUT_SHIFT)
-
-#define STPMU1_VREF_EN			BIT(0)
-
-#define STPMU1_LDO_EN			BIT(0)
-#define STPMU1_LDO12356_OUTPUT_MASK	GENMASK(6, 2)
-#define STPMU1_LDO12356_OUTPUT_SHIFT	2
-#define STPMU1_LDO3_MODE		BIT(7)
-#define STPMU1_LDO3_DDR_SEL		31
-#define STPMU1_LDO3_1800000		(9 << STPMU1_LDO12356_OUTPUT_SHIFT)
-#define STPMU1_LDO4_UV			3300000
-
-#define STPMU1_USB_BOOST_EN		BIT(0)
-#define STPMU1_USB_PWR_SW_EN		GENMASK(2, 1)
-
-#define STPMU1_NVM_USER_CONTROL_PROGRAM	BIT(0)
-#define STPMU1_NVM_USER_CONTROL_READ	BIT(1)
-
-#define STPMU1_NVM_USER_STATUS_BUSY	BIT(0)
-#define STPMU1_NVM_USER_STATUS_ERROR	BIT(1)
-
-#define STPMU1_DEFAULT_START_UP_DELAY_MS	1
-#define STPMU1_DEFAULT_STOP_DELAY_MS		5
-#define STPMU1_USB_BOOST_START_UP_DELAY_MS	10
-
-enum {
-	STPMU1_BUCK1,
-	STPMU1_BUCK2,
-	STPMU1_BUCK3,
-	STPMU1_BUCK4,
-	STPMU1_MAX_BUCK,
-};
-
-enum {
-	STPMU1_BUCK_MODE_HP,
-	STPMU1_BUCK_MODE_LP,
-};
-
-enum {
-	STPMU1_LDO1,
-	STPMU1_LDO2,
-	STPMU1_LDO3,
-	STPMU1_LDO4,
-	STPMU1_LDO5,
-	STPMU1_LDO6,
-	STPMU1_MAX_LDO,
-};
-
-enum {
-	STPMU1_LDO_MODE_NORMAL,
-	STPMU1_LDO_MODE_BYPASS,
-	STPMU1_LDO_MODE_SINK_SOURCE,
-};
-
-enum {
-	STPMU1_PWR_SW1,
-	STPMU1_PWR_SW2,
-	STPMU1_MAX_PWR_SW,
-};
-
-#endif
diff --git a/include/spi.h b/include/spi.h
index 92427e5..3785941 100644
--- a/include/spi.h
+++ b/include/spi.h
@@ -496,14 +496,15 @@
  * device and slave device.
  *
  * If no such slave exists, and drv_name is not NULL, then a new slave device
- * is automatically bound on this chip select.
+ * is automatically bound on this chip select with requested speed and mode.
  *
- * Ths new slave device is probed ready for use with the given speed and mode.
+ * Ths new slave device is probed ready for use with the speed and mode
+ * from platdata when available or the requested values.
  *
  * @busnum:	SPI bus number
  * @cs:		Chip select to look for
- * @speed:	SPI speed to use for this slave
- * @mode:	SPI mode to use for this slave
+ * @speed:	SPI speed to use for this slave when not available in platdata
+ * @mode:	SPI mode to use for this slave when not available in platdata
  * @drv_name:	Name of driver to attach to this chip select
  * @dev_name:	Name of the new device thus created
  * @busp:	Returns bus device
diff --git a/include/video.h b/include/video.h
index 1d57b48..485071d 100644
--- a/include/video.h
+++ b/include/video.h
@@ -70,6 +70,7 @@
  *		the LCD is updated
  * @cmap:	Colour map for 8-bit-per-pixel displays
  * @fg_col_idx:	Foreground color code (bit 3 = bold, bit 0-2 = color)
+ * @bg_col_idx:	Background color code (bit 3 = bold, bit 0-2 = color)
  */
 struct video_priv {
 	/* Things set up by the driver: */
@@ -92,6 +93,7 @@
 	bool flush_dcache;
 	ushort *cmap;
 	u8 fg_col_idx;
+	u8 bg_col_idx;
 };
 
 /* Placeholder - there are no video operations at present */
diff --git a/lib/Kconfig b/lib/Kconfig
index 8fe5d85..2120216 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -436,4 +436,8 @@
 source lib/efi_loader/Kconfig
 source lib/optee/Kconfig
 
+config TEST_FDTDEC
+	bool "enable fdtdec test"
+	depends on OF_LIBFDT
+
 endmenu
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index a51dc5e..9c9c302 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -45,7 +45,7 @@
 	COMPAT(SAMSUNG_EXYNOS_TMU, "samsung,exynos-tmu"),
 	COMPAT(SAMSUNG_EXYNOS_MIPI_DSI, "samsung,exynos-mipi-dsi"),
 	COMPAT(SAMSUNG_EXYNOS_DWMMC, "samsung,exynos-dwmmc"),
-	COMPAT(GENERIC_SPI_FLASH, "spi-flash"),
+	COMPAT(GENERIC_SPI_FLASH, "jedec,spi-nor"),
 	COMPAT(SAMSUNG_EXYNOS_SYSMMU, "samsung,sysmmu-v3.3"),
 	COMPAT(INTEL_MICROCODE, "intel,microcode"),
 	COMPAT(INTEL_QRK_MRC, "intel,quark-mrc"),
@@ -1261,6 +1261,231 @@
 }
 #endif
 
+int fdtdec_set_phandle(void *blob, int node, uint32_t phandle)
+{
+	fdt32_t value = cpu_to_fdt32(phandle);
+
+	return fdt_setprop(blob, node, "phandle", &value, sizeof(value));
+}
+
+static int fdtdec_init_reserved_memory(void *blob)
+{
+	int na, ns, node, err;
+	fdt32_t value;
+
+	/* inherit #address-cells and #size-cells from the root node */
+	na = fdt_address_cells(blob, 0);
+	ns = fdt_size_cells(blob, 0);
+
+	node = fdt_add_subnode(blob, 0, "reserved-memory");
+	if (node < 0)
+		return node;
+
+	err = fdt_setprop(blob, node, "ranges", NULL, 0);
+	if (err < 0)
+		return err;
+
+	value = cpu_to_fdt32(ns);
+
+	err = fdt_setprop(blob, node, "#size-cells", &value, sizeof(value));
+	if (err < 0)
+		return err;
+
+	value = cpu_to_fdt32(na);
+
+	err = fdt_setprop(blob, node, "#address-cells", &value, sizeof(value));
+	if (err < 0)
+		return err;
+
+	return node;
+}
+
+int fdtdec_add_reserved_memory(void *blob, const char *basename,
+			       const struct fdt_memory *carveout,
+			       uint32_t *phandlep)
+{
+	fdt32_t cells[4] = {}, *ptr = cells;
+	uint32_t upper, lower, phandle;
+	int parent, node, na, ns, err;
+	char name[64];
+
+	/* create an empty /reserved-memory node if one doesn't exist */
+	parent = fdt_path_offset(blob, "/reserved-memory");
+	if (parent < 0) {
+		parent = fdtdec_init_reserved_memory(blob);
+		if (parent < 0)
+			return parent;
+	}
+
+	/* only 1 or 2 #address-cells and #size-cells are supported */
+	na = fdt_address_cells(blob, parent);
+	if (na < 1 || na > 2)
+		return -FDT_ERR_BADNCELLS;
+
+	ns = fdt_size_cells(blob, parent);
+	if (ns < 1 || ns > 2)
+		return -FDT_ERR_BADNCELLS;
+
+	/* find a matching node and return the phandle to that */
+	fdt_for_each_subnode(node, blob, parent) {
+		const char *name = fdt_get_name(blob, node, NULL);
+		phys_addr_t addr, size;
+
+		addr = fdtdec_get_addr_size(blob, node, "reg", &size);
+		if (addr == FDT_ADDR_T_NONE) {
+			debug("failed to read address/size for %s\n", name);
+			continue;
+		}
+
+		if (addr == carveout->start && (addr + size) == carveout->end) {
+			*phandlep = fdt_get_phandle(blob, node);
+			return 0;
+		}
+	}
+
+	/*
+	 * Unpack the start address and generate the name of the new node
+	 * base on the basename and the unit-address.
+	 */
+	lower = fdt_addr_unpack(carveout->start, &upper);
+
+	if (na > 1 && upper > 0)
+		snprintf(name, sizeof(name), "%s@%x,%x", basename, upper,
+			 lower);
+	else {
+		if (upper > 0) {
+			debug("address %08x:%08x exceeds addressable space\n",
+			      upper, lower);
+			return -FDT_ERR_BADVALUE;
+		}
+
+		snprintf(name, sizeof(name), "%s@%x", basename, lower);
+	}
+
+	node = fdt_add_subnode(blob, parent, name);
+	if (node < 0)
+		return node;
+
+	err = fdt_generate_phandle(blob, &phandle);
+	if (err < 0)
+		return err;
+
+	err = fdtdec_set_phandle(blob, node, phandle);
+	if (err < 0)
+		return err;
+
+	/* store one or two address cells */
+	if (na > 1)
+		*ptr++ = cpu_to_fdt32(upper);
+
+	*ptr++ = cpu_to_fdt32(lower);
+
+	/* store one or two size cells */
+	lower = fdt_size_unpack(carveout->end - carveout->start + 1, &upper);
+
+	if (ns > 1)
+		*ptr++ = cpu_to_fdt32(upper);
+
+	*ptr++ = cpu_to_fdt32(lower);
+
+	err = fdt_setprop(blob, node, "reg", cells, (na + ns) * sizeof(*cells));
+	if (err < 0)
+		return err;
+
+	/* return the phandle for the new node for the caller to use */
+	if (phandlep)
+		*phandlep = phandle;
+
+	return 0;
+}
+
+int fdtdec_get_carveout(const void *blob, const char *node, const char *name,
+			unsigned int index, struct fdt_memory *carveout)
+{
+	const fdt32_t *prop;
+	uint32_t phandle;
+	int offset, len;
+	fdt_size_t size;
+
+	offset = fdt_path_offset(blob, node);
+	if (offset < 0)
+		return offset;
+
+	prop = fdt_getprop(blob, offset, name, &len);
+	if (!prop) {
+		debug("failed to get %s for %s\n", name, node);
+		return -FDT_ERR_NOTFOUND;
+	}
+
+	if ((len % sizeof(phandle)) != 0) {
+		debug("invalid phandle property\n");
+		return -FDT_ERR_BADPHANDLE;
+	}
+
+	if (len < (sizeof(phandle) * (index + 1))) {
+		debug("invalid phandle index\n");
+		return -FDT_ERR_BADPHANDLE;
+	}
+
+	phandle = fdt32_to_cpu(prop[index]);
+
+	offset = fdt_node_offset_by_phandle(blob, phandle);
+	if (offset < 0) {
+		debug("failed to find node for phandle %u\n", phandle);
+		return offset;
+	}
+
+	carveout->start = fdtdec_get_addr_size_auto_noparent(blob, offset,
+							     "reg", 0, &size,
+							     true);
+	if (carveout->start == FDT_ADDR_T_NONE) {
+		debug("failed to read address/size from \"reg\" property\n");
+		return -FDT_ERR_NOTFOUND;
+	}
+
+	carveout->end = carveout->start + size - 1;
+
+	return 0;
+}
+
+int fdtdec_set_carveout(void *blob, const char *node, const char *prop_name,
+			unsigned int index, const char *name,
+			const struct fdt_memory *carveout)
+{
+	uint32_t phandle;
+	int err, offset;
+	fdt32_t value;
+
+	/* XXX implement support for multiple phandles */
+	if (index > 0) {
+		debug("invalid index %u\n", index);
+		return -FDT_ERR_BADOFFSET;
+	}
+
+	err = fdtdec_add_reserved_memory(blob, name, carveout, &phandle);
+	if (err < 0) {
+		debug("failed to add reserved memory: %d\n", err);
+		return err;
+	}
+
+	offset = fdt_path_offset(blob, node);
+	if (offset < 0) {
+		debug("failed to find offset for node %s: %d\n", node, offset);
+		return offset;
+	}
+
+	value = cpu_to_fdt32(phandle);
+
+	err = fdt_setprop(blob, offset, prop_name, &value, sizeof(value));
+	if (err < 0) {
+		debug("failed to set %s property for node %s: %d\n", prop_name,
+		      node, err);
+		return err;
+	}
+
+	return 0;
+}
+
 int fdtdec_setup(void)
 {
 #if CONFIG_IS_ENABLED(OF_CONTROL)
diff --git a/lib/fdtdec_test.c b/lib/fdtdec_test.c
index a82e27d..f6defe1 100644
--- a/lib/fdtdec_test.c
+++ b/lib/fdtdec_test.c
@@ -15,48 +15,28 @@
 /* The size of our test fdt blob */
 #define FDT_SIZE	(16 * 1024)
 
-/**
- * Check if an operation failed, and if so, print an error
- *
- * @param oper_name	Name of operation
- * @param err		Error code to check
- *
- * @return 0 if ok, -1 if there was an error
- */
-static int fdt_checkerr(const char *oper_name, int err)
-{
-	if (err) {
-		printf("%s: %s: %s\n", __func__, oper_name, fdt_strerror(err));
-		return -1;
-	}
+#define CHECK(op) ({							\
+		int err = op;						\
+		if (err < 0) {						\
+			printf("%s: %s: %s\n", __func__, #op,		\
+			       fdt_strerror(err));			\
+			return err;					\
+		}							\
+									\
+		err;							\
+	})
 
-	return 0;
-}
+#define CHECKVAL(op, expected) ({					\
+		int err = op;						\
+		if (err != expected) {					\
+			printf("%s: %s: expected %d, but returned %d\n",\
+			       __func__, #op, expected, err);		\
+			return err;					\
+		}							\
+									\
+		err;							\
+	})
 
-/**
- * Check the result of an operation and if incorrect, print an error
- *
- * @param oper_name	Name of operation
- * @param expected	Expected value
- * @param value		Actual value
- *
- * @return 0 if ok, -1 if there was an error
- */
-static int checkval(const char *oper_name, int expected, int value)
-{
-	if (expected != value) {
-		printf("%s: %s: expected %d, but returned %d\n", __func__,
-		       oper_name, expected, value);
-		return -1;
-	}
-
-	return 0;
-}
-
-#define CHECK(op)	if (fdt_checkerr(#op, op)) return -1
-#define CHECKVAL(op, expected)	\
-	if (checkval(#op, expected, op)) \
-		return -1
 #define CHECKOK(op)	CHECKVAL(op, 0)
 
 /* maximum number of nodes / aliases to generate */
@@ -79,7 +59,9 @@
 {
 	char name[20], value[20];
 	const char *s;
+#if defined(DEBUG) && defined(CONFIG_SANDBOX)
 	int fd;
+#endif
 
 	CHECK(fdt_create(fdt, size));
 	CHECK(fdt_finish_reservemap(fdt));
@@ -136,7 +118,7 @@
 	CHECKVAL(make_fdt(blob, FDT_SIZE, aliases, nodes), 0);
 	CHECKVAL(fdtdec_find_aliases_for_id(blob, "i2c",
 			COMPAT_UNKNOWN,
-			list, ARRAY_SIZE(list)), strlen(expect));
+			list, ARRAY_SIZE(list)), (int)strlen(expect));
 
 	/* Check we got the right ones */
 	for (i = 0, s = expect; *s; s++, i++) {
@@ -159,6 +141,156 @@
 	return 0;
 }
 
+static int make_fdt_carveout_device(void *fdt, uint32_t na, uint32_t ns)
+{
+	const char *basename = "/display";
+	struct fdt_memory carveout = {
+#ifdef CONFIG_PHYS_64BIT
+		.start = 0x180000000,
+		.end = 0x18fffffff,
+#else
+		.start = 0x80000000,
+		.end = 0x8fffffff,
+#endif
+	};
+	fdt32_t cells[4], *ptr = cells;
+	uint32_t upper, lower;
+	char name[32];
+	int offset;
+
+	/* store one or two address cells */
+	lower = fdt_addr_unpack(carveout.start, &upper);
+
+	if (na > 1 && upper > 0)
+		snprintf(name, sizeof(name), "%s@%x,%x", basename, upper,
+			 lower);
+	else
+		snprintf(name, sizeof(name), "%s@%x", basename, lower);
+
+	if (na > 1)
+		*ptr++ = cpu_to_fdt32(upper);
+
+	*ptr++ = cpu_to_fdt32(lower);
+
+	/* store one or two size cells */
+	lower = fdt_size_unpack(carveout.end - carveout.start + 1, &upper);
+
+	if (ns > 1)
+		*ptr++ = cpu_to_fdt32(upper);
+
+	*ptr++ = cpu_to_fdt32(lower);
+
+	offset = CHECK(fdt_add_subnode(fdt, 0, name + 1));
+	CHECK(fdt_setprop(fdt, offset, "reg", cells, (na + ns) * sizeof(*cells)));
+
+	return fdtdec_set_carveout(fdt, name, "memory-region", 0,
+				   "framebuffer", &carveout);
+}
+
+static int check_fdt_carveout(void *fdt, uint32_t address_cells,
+			      uint32_t size_cells)
+{
+#ifdef CONFIG_PHYS_64BIT
+	const char *name = "/display@1,80000000";
+	const struct fdt_memory expected = {
+		.start = 0x180000000,
+		.end = 0x18fffffff,
+	};
+#else
+	const char *name = "/display@80000000";
+	const struct fdt_memory expected = {
+		.start = 0x80000000,
+		.end = 0x8fffffff,
+	};
+#endif
+	struct fdt_memory carveout;
+
+	printf("carveout: %pap-%pap na=%u ns=%u: ", &expected.start,
+	       &expected.end, address_cells, size_cells);
+
+	CHECK(fdtdec_get_carveout(fdt, name, "memory-region", 0, &carveout));
+
+	if ((carveout.start != expected.start) ||
+	    (carveout.end != expected.end)) {
+		printf("carveout: %pap-%pap, expected %pap-%pap\n",
+		       &carveout.start, &carveout.end,
+		       &expected.start, &expected.end);
+		return 1;
+	}
+
+	printf("pass\n");
+	return 0;
+}
+
+static int make_fdt_carveout(void *fdt, int size, uint32_t address_cells,
+			     uint32_t size_cells)
+{
+	fdt32_t na = cpu_to_fdt32(address_cells);
+	fdt32_t ns = cpu_to_fdt32(size_cells);
+#if defined(DEBUG) && defined(CONFIG_SANDBOX)
+	char filename[512];
+	int fd;
+#endif
+	int err;
+
+	CHECK(fdt_create(fdt, size));
+	CHECK(fdt_finish_reservemap(fdt));
+	CHECK(fdt_begin_node(fdt, ""));
+	CHECK(fdt_property(fdt, "#address-cells", &na, sizeof(na)));
+	CHECK(fdt_property(fdt, "#size-cells", &ns, sizeof(ns)));
+	CHECK(fdt_end_node(fdt));
+	CHECK(fdt_finish(fdt));
+	CHECK(fdt_pack(fdt));
+
+	CHECK(fdt_open_into(fdt, fdt, FDT_SIZE));
+
+	err = make_fdt_carveout_device(fdt, address_cells, size_cells);
+
+#if defined(DEBUG) && defined(CONFIG_SANDBOX)
+	snprintf(filename, sizeof(filename), "/tmp/fdtdec-carveout-%u-%u.dtb",
+		 address_cells, size_cells);
+
+	fd = os_open(filename, OS_O_CREAT | OS_O_WRONLY);
+	if (fd < 0) {
+		printf("could not open .dtb file to write\n");
+		goto out;
+	}
+
+	os_write(fd, fdt, size);
+	os_close(fd);
+
+out:
+#endif
+	return err;
+}
+
+static int check_carveout(void)
+{
+	void *fdt;
+
+	fdt = malloc(FDT_SIZE);
+	if (!fdt) {
+		printf("%s: out of memory\n", __func__);
+		return 1;
+	}
+
+#ifndef CONFIG_PHYS_64BIT
+	CHECKVAL(make_fdt_carveout(fdt, FDT_SIZE, 1, 1), 0);
+	CHECKOK(check_fdt_carveout(fdt, 1, 1));
+	CHECKVAL(make_fdt_carveout(fdt, FDT_SIZE, 1, 2), 0);
+	CHECKOK(check_fdt_carveout(fdt, 1, 2));
+#else
+	CHECKVAL(make_fdt_carveout(fdt, FDT_SIZE, 1, 1), -FDT_ERR_BADVALUE);
+	CHECKVAL(make_fdt_carveout(fdt, FDT_SIZE, 1, 2), -FDT_ERR_BADVALUE);
+#endif
+	CHECKVAL(make_fdt_carveout(fdt, FDT_SIZE, 2, 1), 0);
+	CHECKOK(check_fdt_carveout(fdt, 2, 1));
+	CHECKVAL(make_fdt_carveout(fdt, FDT_SIZE, 2, 2), 0);
+	CHECKOK(check_fdt_carveout(fdt, 2, 2));
+
+	return 0;
+}
+
 static int do_test_fdtdec(cmd_tbl_t *cmdtp, int flag, int argc,
 			  char * const argv[])
 {
@@ -200,6 +332,8 @@
 	CHECKOK(run_test("2a 1a 0a", "a", "  a"));
 	CHECKOK(run_test("0a 1a 2a", "a", "a"));
 
+	CHECKOK(check_carveout());
+
 	printf("Test passed\n");
 	return 0;
 }
diff --git a/lib/libfdt/fdt_ro.c b/lib/libfdt/fdt_ro.c
index b6ca4e0..693de9a 100644
--- a/lib/libfdt/fdt_ro.c
+++ b/lib/libfdt/fdt_ro.c
@@ -73,6 +73,37 @@
 	return 0;
 }
 
+int fdt_generate_phandle(const void *fdt, uint32_t *phandle)
+{
+	uint32_t max = 0;
+	int offset = -1;
+
+	while (true) {
+		uint32_t value;
+
+		offset = fdt_next_node(fdt, offset, NULL);
+		if (offset < 0) {
+			if (offset == -FDT_ERR_NOTFOUND)
+				break;
+
+			return offset;
+		}
+
+		value = fdt_get_phandle(fdt, offset);
+
+		if (value > max)
+			max = value;
+	}
+
+	if (max == FDT_MAX_PHANDLE)
+		return -FDT_ERR_NOPHANDLES;
+
+	if (phandle)
+		*phandle = max + 1;
+
+	return 0;
+}
+
 int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
 {
 	FDT_CHECK_HEADER(fdt);
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 1b6c154..2403825 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -457,7 +457,6 @@
 		return device_path_string(buf, end, ptr, field_width,
 					  precision, flags);
 #endif
-#ifdef CONFIG_CMD_NET
 	case 'a':
 		flags |= SPECIAL | ZEROPAD;
 
@@ -469,6 +468,7 @@
 			break;
 		}
 		break;
+#ifdef CONFIG_CMD_NET
 	case 'm':
 		flags |= SPECIAL;
 		/* Fallthrough */
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 70de9bb..de67677 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -525,4 +525,5 @@
       cmd_fdtgrep = $(objtree)/tools/fdtgrep $(fdtgrep_props) -RT $< \
 		-n /chosen -n /config -O dtb | \
 	$(objtree)/tools/fdtgrep -r -O dtb - -o $@ \
+		-P u-boot,dm-pre-reloc -P u-boot,dm-spl -P u-boot,dm-tpl \
 		$(addprefix -P ,$(subst $\",,$(CONFIG_OF_SPL_REMOVE_PROPS)))
diff --git a/scripts/dtc/libfdt/fdt_ro.c b/scripts/dtc/libfdt/fdt_ro.c
index dfb3236..dc49988 100644
--- a/scripts/dtc/libfdt/fdt_ro.c
+++ b/scripts/dtc/libfdt/fdt_ro.c
@@ -115,6 +115,37 @@
 	return 0;
 }
 
+int fdt_generate_phandle(const void *fdt, uint32_t *phandle)
+{
+	uint32_t max = 0;
+	int offset = -1;
+
+	while (true) {
+		uint32_t value;
+
+		offset = fdt_next_node(fdt, offset, NULL);
+		if (offset < 0) {
+			if (offset == -FDT_ERR_NOTFOUND)
+				break;
+
+			return offset;
+		}
+
+		value = fdt_get_phandle(fdt, offset);
+
+		if (value > max)
+			max = value;
+	}
+
+	if (max == FDT_MAX_PHANDLE)
+		return -FDT_ERR_NOPHANDLES;
+
+	if (phandle)
+		*phandle = max + 1;
+
+	return 0;
+}
+
 int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
 {
 	FDT_CHECK_HEADER(fdt);
diff --git a/scripts/dtc/libfdt/libfdt.h b/scripts/dtc/libfdt/libfdt.h
index fd73688..cf86ddb 100644
--- a/scripts/dtc/libfdt/libfdt.h
+++ b/scripts/dtc/libfdt/libfdt.h
@@ -139,6 +139,10 @@
 
 #define FDT_ERR_MAX		17
 
+/* constants */
+#define FDT_MAX_PHANDLE 0xfffffffe
+	/* Valid values for phandles range from 1 to 2^32-2. */
+
 /**********************************************************************/
 /* Low-level functions (you probably don't need these)                */
 /**********************************************************************/
@@ -314,6 +318,21 @@
 uint32_t fdt_get_max_phandle(const void *fdt);
 
 /**
+ * fdt_generate_phandle - return a new, unused phandle for a device tree blob
+ * @fdt: pointer to the device tree blob
+ * @phandle: return location for the new phandle
+ *
+ * Walks the device tree blob and looks for the highest phandle value. On
+ * success, the new, unused phandle value (one higher than the previously
+ * highest phandle value in the device tree blob) will be returned in the
+ * @phandle parameter.
+ *
+ * Returns:
+ *   0 on success or a negative error-code on failure
+ */
+int fdt_generate_phandle(const void *fdt, uint32_t *phandle);
+
+/**
  * fdt_num_mem_rsv - retrieve the number of memory reserve map entries
  * @fdt: pointer to the device tree blob
  *
diff --git a/scripts/dtc/libfdt/libfdt_env.h b/scripts/dtc/libfdt/libfdt_env.h
index bd24746..3ff9e28 100644
--- a/scripts/dtc/libfdt/libfdt_env.h
+++ b/scripts/dtc/libfdt/libfdt_env.h
@@ -52,6 +52,7 @@
  *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <stdbool.h>
 #include <stddef.h>
 #include <stdint.h>
 #include <stdlib.h>
diff --git a/test/dm/syscon.c b/test/dm/syscon.c
index a294dda..0ff9da7 100644
--- a/test/dm/syscon.c
+++ b/test/dm/syscon.c
@@ -67,6 +67,13 @@
 	ut_assert(!IS_ERR(map));
 	ut_asserteq(4, map->range_count);
 
+	ut_assertok_ptr(syscon_regmap_lookup_by_phandle(dev,
+							"third-syscon"));
+	map = syscon_regmap_lookup_by_phandle(dev, "third-syscon");
+	ut_assert(map);
+	ut_assert(!IS_ERR(map));
+	ut_asserteq(4, map->range_count);
+
 	ut_assert(IS_ERR(syscon_regmap_lookup_by_phandle(dev, "not-present")));
 
 	return 0;
diff --git a/tools/kwbimage.c b/tools/kwbimage.c
index a88a383..dffaf90 100644
--- a/tools/kwbimage.c
+++ b/tools/kwbimage.c
@@ -1273,6 +1273,13 @@
 	e = image_find_option(IMAGE_CFG_DEBUG);
 	if (e)
 		main_hdr->flags = e->debug ? 0x1 : 0;
+	e = image_find_option(IMAGE_CFG_BINARY);
+	if (e) {
+		char *s = strrchr(e->binary.file, '/');
+
+		if (strcmp(s, "/binary.0") == 0)
+			main_hdr->destaddr = cpu_to_le32(params->addr);
+	}
 
 #if defined(CONFIG_KWB_SECURE)
 	if (image_get_csk_index() >= 0) {
diff --git a/tools/mkimage.c b/tools/mkimage.c
index 2899adf..d1e1a67 100644
--- a/tools/mkimage.c
+++ b/tools/mkimage.c
@@ -403,14 +403,21 @@
 			exit (EXIT_FAILURE);
 		}
 
-		/*
-		 * scan through mkimage registry for all supported image types
-		 * and verify the input image file header for match
-		 * Print the image information for matched image type
-		 * Returns the error code if not matched
-		 */
-		retval = imagetool_verify_print_header_by_type(ptr, &sbuf,
-				tparams, &params);
+		if (params.fflag) {
+			/*
+			 * Verifies the header format based on the expected header for image
+			 * type in tparams
+			 */
+			retval = imagetool_verify_print_header_by_type(ptr, &sbuf,
+					tparams, &params);
+		} else {
+			/**
+			 * When listing the image, we are not given the image type. Simply check all
+			 * image types to find one that matches our header
+			 */
+			retval = imagetool_verify_print_header(ptr, &sbuf,
+					tparams, &params);
+		}
 
 		(void) munmap((void *)ptr, sbuf.st_size);
 		(void) close (ifd);