Merge tag 'u-boot-imx-20190415' of git://git.denx.de/u-boot-imx

Move to DM
-----------

- DM support in sata
- Toradex Board to DM
- wandboard to DM
- tbs2910 to DM
- GE boards to DM
- VHybrid boards to DM
- DM_VIDEO for i.MX
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 083bf47..c77abba 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -310,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
@@ -691,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/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/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-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-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-theadorable.dts b/arch/arm/dts/armada-xp-theadorable.dts
index bcb4bfd..5b18d62 100644
--- a/arch/arm/dts/armada-xp-theadorable.dts
+++ b/arch/arm/dts/armada-xp-theadorable.dts
@@ -162,7 +162,7 @@
 		u-boot,dm-pre-reloc;
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "n25q128a13", "jedec,spi-nor", "spi-flash";
+		compatible = "n25q128a13", "jedec,spi-nor";
 		reg = <0>; /* Chip select 0 */
 		spi-max-frequency = <27777777>;
 	};
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/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/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/stm32mp157c-ev1-u-boot.dtsi b/arch/arm/dts/stm32mp157c-ev1-u-boot.dtsi
index 6a18d03..8b92b1f 100644
--- a/arch/arm/dts/stm32mp157c-ev1-u-boot.dtsi
+++ b/arch/arm/dts/stm32mp157c-ev1-u-boot.dtsi
@@ -16,12 +16,12 @@
 };
 
 &flash0 {
-	compatible = "spi-flash";
+	compatible = "jedec,spi-nor";
 	u-boot,dm-spl;
 };
 
 &flash1 {
-	compatible = "spi-flash";
+	compatible = "jedec,spi-nor";
 };
 
 &qspi {
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/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/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/lib/interrupts_64.c b/arch/arm/lib/interrupts_64.c
index 458319a..0bfdb8d 100644
--- a/arch/arm/lib/interrupts_64.c
+++ b/arch/arm/lib/interrupts_64.c
@@ -25,6 +25,11 @@
 	return 0;
 }
 
+static void show_efi_loaded_images(struct pt_regs *regs)
+{
+	efi_print_image_infos((void *)regs->elr);
+}
+
 void show_regs(struct pt_regs *regs)
 {
 	int i;
@@ -49,6 +54,7 @@
 	efi_restore_gd();
 	printf("Bad mode in \"Synchronous Abort\" handler, esr 0x%08x\n", esr);
 	show_regs(pt_regs);
+	show_efi_loaded_images(pt_regs);
 	panic("Resetting CPU ...\n");
 }
 
@@ -60,6 +66,7 @@
 	efi_restore_gd();
 	printf("Bad mode in \"Irq\" handler, esr 0x%08x\n", esr);
 	show_regs(pt_regs);
+	show_efi_loaded_images(pt_regs);
 	panic("Resetting CPU ...\n");
 }
 
@@ -71,6 +78,7 @@
 	efi_restore_gd();
 	printf("Bad mode in \"Fiq\" handler, esr 0x%08x\n", esr);
 	show_regs(pt_regs);
+	show_efi_loaded_images(pt_regs);
 	panic("Resetting CPU ...\n");
 }
 
@@ -82,6 +90,7 @@
 	efi_restore_gd();
 	printf("Bad mode in \"Error\" handler, esr 0x%08x\n", esr);
 	show_regs(pt_regs);
+	show_efi_loaded_images(pt_regs);
 	panic("Resetting CPU ...\n");
 }
 
@@ -93,6 +102,7 @@
 	efi_restore_gd();
 	printf("\"Synchronous Abort\" handler, esr 0x%08x\n", esr);
 	show_regs(pt_regs);
+	show_efi_loaded_images(pt_regs);
 	panic("Resetting CPU ...\n");
 }
 
@@ -104,6 +114,7 @@
 	efi_restore_gd();
 	printf("\"Irq\" handler, esr 0x%08x\n", esr);
 	show_regs(pt_regs);
+	show_efi_loaded_images(pt_regs);
 	panic("Resetting CPU ...\n");
 }
 
@@ -115,6 +126,7 @@
 	efi_restore_gd();
 	printf("\"Fiq\" handler, esr 0x%08x\n", esr);
 	show_regs(pt_regs);
+	show_efi_loaded_images(pt_regs);
 	panic("Resetting CPU ...\n");
 }
 
@@ -129,5 +141,6 @@
 	efi_restore_gd();
 	printf("\"Error\" handler, esr 0x%08x\n", esr);
 	show_regs(pt_regs);
+	show_efi_loaded_images(pt_regs);
 	panic("Resetting CPU ...\n");
 }
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/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/sunxi/MAINTAINERS b/board/sunxi/MAINTAINERS
index 7f96d2b..338f374 100644
--- a/board/sunxi/MAINTAINERS
+++ b/board/sunxi/MAINTAINERS
@@ -353,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/cmd/bootefi.c b/cmd/bootefi.c
index 3619a20..15ee4af 100644
--- a/cmd/bootefi.c
+++ b/cmd/bootefi.c
@@ -111,13 +111,13 @@
 	new_fdt_addr = (uintptr_t)map_sysmem(fdt_ram_start + 0x7f00000 +
 					     fdt_size, 0);
 	ret = efi_allocate_pages(EFI_ALLOCATE_MAX_ADDRESS,
-				 EFI_RUNTIME_SERVICES_DATA, fdt_pages,
+				 EFI_BOOT_SERVICES_DATA, fdt_pages,
 				 &new_fdt_addr);
 	if (ret != EFI_SUCCESS) {
 		/* If we can't put it there, put it somewhere */
 		new_fdt_addr = (ulong)memalign(EFI_PAGE_SIZE, fdt_size);
 		ret = efi_allocate_pages(EFI_ALLOCATE_MAX_ADDRESS,
-					 EFI_RUNTIME_SERVICES_DATA, fdt_pages,
+					 EFI_BOOT_SERVICES_DATA, fdt_pages,
 					 &new_fdt_addr);
 		if (ret != EFI_SUCCESS) {
 			printf("ERROR: Failed to reserve space for FDT\n");
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/common/board_r.c b/common/board_r.c
index 472987d..1ad44bb 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -154,6 +154,13 @@
 	gd->fdt_blob += gd->reloc_off;
 #endif
 #ifdef CONFIG_EFI_LOADER
+	/*
+	 * On the ARM architecture gd is mapped to a fixed register (r9 or x18).
+	 * As this register may be overwritten by an EFI payload we save it here
+	 * and restore it on every callback entered.
+	 */
+	efi_save_gd();
+
 	efi_runtime_relocate(gd->relocaddr, NULL);
 #endif
 
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/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/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/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/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/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/README.uefi b/doc/README.uefi
index 66b6abe..1d1039a 100644
--- a/doc/README.uefi
+++ b/doc/README.uefi
@@ -14,9 +14,11 @@
 
 ## Development target
 
-The implementation of UEFI in U-Boot strives to reach the minimum requirements
-described in "Server Base Boot Requirements System Software on ARM Platforms -
-Version 1.1" [4].
+The implementation of UEFI in U-Boot strives to reach the requirements described
+in the "Embedded Base Boot Requirements (EBBR) Specification - Release v1.0"
+[4]. The "Server Base Boot Requirements System Software on ARM Platforms" [5]
+describes a superset of the EBBR specification and may be used as further
+reference.
 
 A full blown UEFI implementation would contradict the U-Boot design principle
 "keep it small".
@@ -344,5 +346,7 @@
   http://uefi.org/specifications - UEFI specifications
 * [2](./driver-model/README.txt) doc/driver-model/README.txt - Driver model
 * [3](./README.iscsi) doc/README.iscsi - iSCSI booting with U-Boot and iPXE
-* [4](https://developer.arm.com/docs/den0044/latest/server-base-boot-requirements-system-software-on-arm-platforms-version-11)
+* [4](https://github.com/ARM-software/ebbr/releases/download/v1.0/ebbr-v1.0.pdf)
+  Embedded Base Boot Requirements (EBBR) Specification - Release v1.0
+* [5](https://developer.arm.com/docs/den0044/latest/server-base-boot-requirements-system-software-on-arm-platforms-version-11)
   Server Base Boot Requirements System Software on ARM Platforms - Version 1.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 ec6d8bf..f989792 100644
--- a/doc/git-mailrc
+++ b/doc/git-mailrc
@@ -24,7 +24,7 @@
 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 lukma          Lukasz Majewski <lukma@denx.de>
 alias macpaul        Macpaul Lin <macpaul@andestech.com>
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/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/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/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/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/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-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/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/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 53871f8..c3781b1 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/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/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/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/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/efi.h b/include/efi.h
index d98441a..3c9d20f 100644
--- a/include/efi.h
+++ b/include/efi.h
@@ -190,7 +190,7 @@
 #define EFI_MEM_DESC_VERSION	1
 
 #define EFI_PAGE_SHIFT		12
-#define EFI_PAGE_SIZE		(1UL << EFI_PAGE_SHIFT)
+#define EFI_PAGE_SIZE		(1ULL << EFI_PAGE_SHIFT)
 #define EFI_PAGE_MASK		(EFI_PAGE_SIZE - 1)
 
 struct efi_mem_desc {
diff --git a/include/efi_loader.h b/include/efi_loader.h
index 00b81c6..f7bf732 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -344,6 +344,9 @@
 				 void *protocol_interface);
 /* Delete all protocols from a handle */
 efi_status_t efi_remove_all_protocols(const efi_handle_t handle);
+/* Install multiple protocol interfaces */
+efi_status_t EFIAPI efi_install_multiple_protocol_interfaces
+				(efi_handle_t *handle, ...);
 /* Call this to create an event */
 efi_status_t efi_create_event(uint32_t type, efi_uintn_t notify_tpl,
 			      void (EFIAPI *notify_function) (
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/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/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/efi_driver/efi_uclass.c b/lib/efi_driver/efi_uclass.c
index 7cdf81f..b14746e 100644
--- a/lib/efi_driver/efi_uclass.c
+++ b/lib/efi_driver/efi_uclass.c
@@ -300,9 +300,6 @@
 	struct driver *drv;
 	efi_status_t ret = EFI_SUCCESS;
 
-	/* Save 'gd' pointer */
-	efi_save_gd();
-
 	debug("EFI: Initializing EFI driver framework\n");
 	for (drv = ll_entry_start(struct driver, driver);
 	     drv < ll_entry_end(struct driver, driver); ++drv) {
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index 23487b8..50b0501 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -26,6 +26,16 @@
 	  set, only the the correct handling of the letters of the codepage
 	  used by the FAT file system is ensured.
 
+config EFI_PLATFORM_LANG_CODES
+	string "Language codes supported by firmware"
+	depends on EFI_LOADER
+	default "en-US"
+	help
+	  This value is used to initialize the PlatformLangCodes variable. Its
+	  value is a semicolon (;) separated list of language codes in native
+	  RFC 4646 format, e.g. "en-US;de-DE". The first language code is used
+	  to initialize the PlatformLang variable.
+
 config EFI_LOADER_BOUNCE_BUFFER
 	bool "EFI Applications use bounce buffers for DMA operations"
 	depends on EFI_LOADER && ARM64
@@ -38,14 +48,11 @@
 config EFI_LOADER_HII
 	bool "Expose HII protocols to EFI applications"
 	depends on EFI_LOADER
-	default n
+	default y
 	help
 	  The Human Interface Infrastructure is a complicated framework that
 	  allows UEFI applications to draw fancy menus and hook strings using
 	  a translation framework.
 
 	  U-Boot implements enough of its features to be able to run the UEFI
-	  Shell, but not more than that. The code is experimental still, so
-	  beware that your system might break with HII enabled.
-
-	  If unsure, say n.
+	  Shell, but not more than that.
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index b215bd7..abc295e 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -1569,26 +1569,6 @@
 	if (ret != EFI_SUCCESS)
 		goto failure;
 
-#if CONFIG_IS_ENABLED(EFI_LOADER_HII)
-	ret = efi_add_protocol(&obj->header,
-			       &efi_guid_hii_string_protocol,
-			       (void *)&efi_hii_string);
-	if (ret != EFI_SUCCESS)
-		goto failure;
-
-	ret = efi_add_protocol(&obj->header,
-			       &efi_guid_hii_database_protocol,
-			       (void *)&efi_hii_database);
-	if (ret != EFI_SUCCESS)
-		goto failure;
-
-	ret = efi_add_protocol(&obj->header,
-			       &efi_guid_hii_config_routing_protocol,
-			       (void *)&efi_hii_config_routing);
-	if (ret != EFI_SUCCESS)
-		goto failure;
-#endif
-
 	*info_ptr = info;
 	*handle_ptr = obj;
 
@@ -2287,7 +2267,7 @@
  *
  * Return: status code
  */
-static efi_status_t EFIAPI efi_install_multiple_protocol_interfaces
+efi_status_t EFIAPI efi_install_multiple_protocol_interfaces
 				(efi_handle_t *handle, ...)
 {
 	EFI_ENTRY("%p", handle);
diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c
index 53b40c8..d8c052d 100644
--- a/lib/efi_loader/efi_device_path.c
+++ b/lib/efi_loader/efi_device_path.c
@@ -5,8 +5,6 @@
  * (C) Copyright 2017 Rob Clark
  */
 
-#define LOG_CATEGORY LOGL_ERR
-
 #include <common.h>
 #include <blk.h>
 #include <dm.h>
@@ -970,7 +968,7 @@
 	if (!is_net) {
 		part = blk_get_device_part_str(dev, devnr, &desc, &fs_partition,
 					       1);
-		if (part < 0)
+		if (part < 0 || !desc)
 			return EFI_INVALID_PARAMETER;
 
 		if (device)
diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
index dbe29b8..46681dc 100644
--- a/lib/efi_loader/efi_memory.c
+++ b/lib/efi_loader/efi_memory.c
@@ -193,6 +193,7 @@
 			free(map);
 		} else {
 			map->desc.physical_start = carve_end;
+			map->desc.virtual_start = carve_end;
 			map->desc.num_pages = (map_end - carve_end)
 					      >> EFI_PAGE_SHIFT;
 		}
@@ -211,6 +212,7 @@
 	newmap = calloc(1, sizeof(*newmap));
 	newmap->desc = map->desc;
 	newmap->desc.physical_start = carve_start;
+	newmap->desc.virtual_start = carve_start;
 	newmap->desc.num_pages = (map_end - carve_start) >> EFI_PAGE_SHIFT;
 	/* Insert before current entry (descending address order) */
 	list_add_tail(&newmap->link, &map->link);
diff --git a/lib/efi_loader/efi_root_node.c b/lib/efi_loader/efi_root_node.c
index b056ba3..392f5c4 100644
--- a/lib/efi_loader/efi_root_node.c
+++ b/lib/efi_loader/efi_root_node.c
@@ -26,16 +26,10 @@
  */
 efi_status_t efi_root_node_register(void)
 {
-	efi_handle_t root;
-	efi_status_t ret;
+	efi_handle_t root = NULL;
 	struct efi_root_dp *dp;
 
-	/* Create handle */
-	ret = efi_create_handle(&root);
-	if (ret != EFI_SUCCESS)
-		return ret;
-
-	/* Install device path protocol */
+	/* Create device path protocol */
 	dp = calloc(1, sizeof(*dp));
 	if (!dp)
 		return EFI_OUT_OF_RESOURCES;
@@ -51,29 +45,29 @@
 	dp->end.sub_type = DEVICE_PATH_SUB_TYPE_END;
 	dp->end.length = sizeof(struct efi_device_path);
 
-	/* Install device path protocol */
-	ret = efi_add_protocol(root, &efi_guid_device_path, dp);
-	if (ret != EFI_SUCCESS)
-		goto failure;
-
-	/* Install device path to text protocol */
-	ret = efi_add_protocol(root, &efi_guid_device_path_to_text_protocol,
-			       (void *)&efi_device_path_to_text);
-	if (ret != EFI_SUCCESS)
-		goto failure;
-
-	/* Install device path utilities protocol */
-	ret = efi_add_protocol(root, &efi_guid_device_path_utilities_protocol,
-			       (void *)&efi_device_path_utilities);
-	if (ret != EFI_SUCCESS)
-		goto failure;
-
-	/* Install Unicode collation protocol */
-	ret = efi_add_protocol(root, &efi_guid_unicode_collation_protocol,
-			       (void *)&efi_unicode_collation_protocol);
-	if (ret != EFI_SUCCESS)
-		goto failure;
-
-failure:
-	return ret;
+	/* Create root node and install protocols */
+	return EFI_CALL(efi_install_multiple_protocol_interfaces(&root,
+		       /* Device path protocol */
+		       &efi_guid_device_path, dp,
+		       /* Device path to text protocol */
+		       &efi_guid_device_path_to_text_protocol,
+		       (void *)&efi_device_path_to_text,
+		       /* Device path utilities protocol */
+		       &efi_guid_device_path_utilities_protocol,
+		       (void *)&efi_device_path_utilities,
+		       /* Unicode collation protocol */
+		       &efi_guid_unicode_collation_protocol,
+		       (void *)&efi_unicode_collation_protocol,
+#if CONFIG_IS_ENABLED(EFI_LOADER_HII)
+		       /* HII string protocol */
+		       &efi_guid_hii_string_protocol,
+		       (void *)&efi_hii_string,
+		       /* HII database protocol */
+		       &efi_guid_hii_database_protocol,
+		       (void *)&efi_hii_database,
+		       /* HII configuration routing protocol */
+		       &efi_guid_hii_config_routing_protocol,
+		       (void *)&efi_hii_config_routing,
+#endif
+		       NULL));
 }
diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c
index a908843..b32a7b3 100644
--- a/lib/efi_loader/efi_setup.c
+++ b/lib/efi_loader/efi_setup.c
@@ -10,51 +10,86 @@
 
 #define OBJ_LIST_NOT_INITIALIZED 1
 
-/* Language code for American English according to RFC 4646 */
-#define EN_US L"en-US"
-
 static efi_status_t efi_obj_list_initialized = OBJ_LIST_NOT_INITIALIZED;
 
-/* Initialize and populate EFI object list */
-efi_status_t efi_init_obj_list(void)
+/**
+ * efi_init_platform_lang() - define supported languages
+ *
+ * Set the PlatformLangCodes and PlatformLang variables.
+ *
+ * Return:	status code
+ */
+static efi_status_t efi_init_platform_lang(void)
 {
-	efi_status_t ret = EFI_SUCCESS;
+	efi_status_t ret;
+	efi_uintn_t data_size = 0;
+	char *lang = CONFIG_EFI_PLATFORM_LANG_CODES;
+	char *pos;
 
 	/*
-	 * On the ARM architecture gd is mapped to a fixed register (r9 or x18).
-	 * As this register may be overwritten by an EFI payload we save it here
-	 * and restore it on every callback entered.
+	 * Variable PlatformLangCodes defines the language codes that the
+	 * machine can support.
 	 */
-	efi_save_gd();
+	ret = EFI_CALL(efi_set_variable(L"PlatformLangCodes",
+					&efi_global_variable_guid,
+					EFI_VARIABLE_BOOTSERVICE_ACCESS |
+					EFI_VARIABLE_RUNTIME_ACCESS,
+					sizeof(CONFIG_EFI_PLATFORM_LANG_CODES),
+					CONFIG_EFI_PLATFORM_LANG_CODES));
+	if (ret != EFI_SUCCESS)
+		goto out;
 
 	/*
 	 * Variable PlatformLang defines the language that the machine has been
 	 * configured for.
 	 */
-	ret = EFI_CALL(efi_set_variable(L"PlatformLang",
+	ret = EFI_CALL(efi_get_variable(L"PlatformLang",
 					&efi_global_variable_guid,
-					EFI_VARIABLE_BOOTSERVICE_ACCESS |
-					EFI_VARIABLE_RUNTIME_ACCESS,
-					sizeof(EN_US), EN_US));
-	if (ret != EFI_SUCCESS)
+					NULL, &data_size, &pos));
+	if (ret == EFI_BUFFER_TOO_SMALL) {
+		/* The variable is already set. Do not change it. */
+		ret = EFI_SUCCESS;
 		goto out;
+	}
 
 	/*
-	 * Variable PlatformLangCodes defines the language codes that the
-	 * machine can support.
+	 * The list of supported languages is semicolon separated. Use the first
+	 * language to initialize PlatformLang.
 	 */
-	ret = EFI_CALL(efi_set_variable(L"PlatformLangCodes",
+	pos = strchr(lang, ';');
+	if (pos)
+		*pos = 0;
+
+	ret = EFI_CALL(efi_set_variable(L"PlatformLang",
 					&efi_global_variable_guid,
+					EFI_VARIABLE_NON_VOLATILE |
 					EFI_VARIABLE_BOOTSERVICE_ACCESS |
 					EFI_VARIABLE_RUNTIME_ACCESS,
-					sizeof(EN_US), EN_US));
+					1 + strlen(lang), lang));
+out:
 	if (ret != EFI_SUCCESS)
-		goto out;
+		printf("EFI: cannot initialize platform language settings\n");
+	return ret;
+}
+
+/**
+ * efi_init_obj_list() - Initialize and populate EFI object list
+ *
+ * Return:	status code
+ */
+efi_status_t efi_init_obj_list(void)
+{
+	efi_status_t ret = EFI_SUCCESS;
 
 	/* Initialize once only */
 	if (efi_obj_list_initialized != OBJ_LIST_NOT_INITIALIZED)
 		return efi_obj_list_initialized;
 
+	/* Define supported languages */
+	ret = efi_init_platform_lang();
+	if (ret != EFI_SUCCESS)
+		goto out;
+
 	/* Initialize system table */
 	ret = efi_initialize_system_table();
 	if (ret != EFI_SUCCESS)
diff --git a/lib/efi_selftest/efi_selftest_memory.c b/lib/efi_selftest/efi_selftest_memory.c
index 24b4438..5eeb42a 100644
--- a/lib/efi_selftest/efi_selftest_memory.c
+++ b/lib/efi_selftest/efi_selftest_memory.c
@@ -4,7 +4,7 @@
  *
  * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
  *
- * This unit test checks the following runtime services:
+ * This unit test checks the following boottime services:
  * AllocatePages, FreePages, GetMemoryMap
  *
  * The memory type used for the device tree is checked.
@@ -65,6 +65,11 @@
 	for (i = 0; map_size; ++i, map_size -= desc_size) {
 		struct efi_mem_desc *entry = &memory_map[i];
 
+		if (entry->physical_start != entry->virtual_start) {
+			efi_st_error("Physical and virtual addresses do not match\n");
+			return EFI_ST_FAILURE;
+		}
+
 		if (addr >= entry->physical_start &&
 		    addr < entry->physical_start +
 			    (entry->num_pages << EFI_PAGE_SHIFT)) {
@@ -171,9 +176,9 @@
 	/* Check memory reservation for the device tree */
 	if (fdt_addr &&
 	    find_in_memory_map(map_size, memory_map, desc_size, fdt_addr,
-			       EFI_RUNTIME_SERVICES_DATA) != EFI_ST_SUCCESS) {
+			       EFI_BOOT_SERVICES_DATA) != EFI_ST_SUCCESS) {
 		efi_st_error
-			("Device tree not marked as runtime services data\n");
+			("Device tree not marked as boot services data\n");
 		return EFI_ST_FAILURE;
 	}
 	return EFI_ST_SUCCESS;
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/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);