Merge git://git.denx.de/u-boot-rockchip
diff --git a/Makefile b/Makefile
index fffc188..c30f90a 100644
--- a/Makefile
+++ b/Makefile
@@ -936,8 +936,19 @@
 u-boot.dis:	u-boot
 		$(OBJDUMP) -d $< > $@
 
+# If .u-boot.cfg.d is still present, then either:
+# a) The previous build used a Makefile that used if_changed rather than
+#    if_changed_dep when building u-boot.cfg, and hence any later builds will
+#    be unaware of the dependencies for u-boot.cfg. In this case, we must
+#    delete u-boot.cfg to force it and .u-boot.cfg.cmd to be rebuilt the
+#    correct way.
+# b) The previous build failed or was interrupted while building u-boot.cfg,
+#    so deleting u-boot.cfg isn't going to cause any additional work.
+ifneq ($(wildcard $(obj)/.u-boot.cfg.d),)
+  unused := $(shell rm -f $(obj)/u-boot.cfg)
+endif
 u-boot.cfg:	include/config.h FORCE
-	$(call if_changed,cpp_cfg)
+	$(call if_changed_dep,cpp_cfg)
 
 # Check that this build does not use CONFIG options that we don't know about
 # unless they are in Kconfig. All the existing CONFIG options are whitelisted,
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 9b85635..0083bf9 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -868,6 +868,8 @@
 	select PINCTRL
 	select SPL
 	select SPL_DM
+	select SPL_LIBCOMMON_SUPPORT
+	select SPL_LIBGENERIC_SUPPORT
 	select SPL_OF_CONTROL
 	select SPL_PINCTRL
 	select SUPPORT_SPL
diff --git a/arch/arm/cpu/armv8/zynqmp/Kconfig b/arch/arm/cpu/armv8/zynqmp/Kconfig
index e703991..1eedb39 100644
--- a/arch/arm/cpu/armv8/zynqmp/Kconfig
+++ b/arch/arm/cpu/armv8/zynqmp/Kconfig
@@ -47,5 +47,53 @@
 config SYS_MALLOC_F_LEN
 	default 0x600
 
+config SPL_ZYNQMP_ALT_BOOTMODE_ENABLED
+	bool "Overwrite SPL bootmode"
+	depends on SPL
+	help
+	  Overwrite bootmode selected via boot mode pins to tell SPL what should
+	  be the next boot device.
+
+config SPL_ZYNQMP_ALT_BOOTMODE
+	hex
+	default 0x0 if JTAG_MODE
+	default 0x1 if QSPI_MODE_24BIT
+	default 0x2 if QSPI_MODE_32BIT
+	default 0x3 if SD_MODE
+	default 0x4 if NAND_MODE
+	default 0x5 if SD_MODE1
+	default 0x6 if EMMC_MODE
+	default 0x7 if USB_MODE
+
+choice
+	prompt "Boot mode"
+	depends on ZYNQMP_ALT_BOOTMODE_ENABLED
+	default JTAG
+
+config JTAG_MODE
+	bool "JTAG_MODE"
+
+config QSPI_MODE_24BIT
+	bool "QSPI_MODE_24BIT"
+
+config QSPI_MODE_32BIT
+	bool "QSPI_MODE_32BIT"
+
+config SD_MODE
+	bool "SD_MODE"
+
+config SD_MODE1
+	bool "SD_MODE1"
+
+config NAND_MODE
+	bool "NAND_MODE"
+
+config EMMC_MODE
+	bool "EMMC_MODE"
+
+config USB_MODE
+	bool "USB"
+
+endchoice
 
 endif
diff --git a/arch/arm/cpu/armv8/zynqmp/spl.c b/arch/arm/cpu/armv8/zynqmp/spl.c
index 867d2b2..04e1905 100644
--- a/arch/arm/cpu/armv8/zynqmp/spl.c
+++ b/arch/arm/cpu/armv8/zynqmp/spl.c
@@ -35,10 +35,29 @@
 	board_init_r(NULL, 0);
 }
 
+static void ps_mode_reset(ulong mode)
+{
+	writel(mode << ZYNQMP_CRL_APB_BOOT_PIN_CTRL_OUT_EN_SHIFT,
+	       &crlapb_base->boot_pin_ctrl);
+	udelay(5);
+	writel(mode << ZYNQMP_CRL_APB_BOOT_PIN_CTRL_OUT_VAL_SHIFT |
+	       mode << ZYNQMP_CRL_APB_BOOT_PIN_CTRL_OUT_EN_SHIFT,
+	       &crlapb_base->boot_pin_ctrl);
+}
+
+/*
+ * Set default PS_MODE1 which is used for USB ULPI phy reset
+ * Also other resets can be connected to this certain pin
+ */
+#ifndef MODE_RESET
+# define MODE_RESET	PS_MODE1
+#endif
+
 #ifdef CONFIG_SPL_BOARD_INIT
 void spl_board_init(void)
 {
 	preloader_console_init();
+	ps_mode_reset(MODE_RESET);
 	board_init();
 }
 #endif
@@ -48,6 +67,13 @@
 	u32 reg = 0;
 	u8 bootmode;
 
+#if defined(CONFIG_SPL_ZYNQMP_ALT_BOOTMODE_ENABLED)
+	/* Change default boot mode at run-time */
+	writel(BOOT_MODE_USE_ALT |
+	       CONFIG_SPL_ZYNQMP_ALT_BOOTMODE << BOOT_MODE_ALT_SHIFT,
+	       &crlapb_base->boot_mode);
+#endif
+
 	reg = readl(&crlapb_base->boot_mode);
 	bootmode = reg & BOOT_MODES_MASK;
 
@@ -60,6 +86,10 @@
 	case SD_MODE1:
 		return BOOT_DEVICE_MMC1;
 #endif
+#ifdef CONFIG_SPL_DFU_SUPPORT
+	case USB_MODE:
+		return BOOT_DEVICE_DFU;
+#endif
 	default:
 		printf("Invalid Boot Mode:0x%x\n", bootmode);
 		break;
diff --git a/arch/arm/dts/uniphier-common32.dtsi b/arch/arm/dts/uniphier-common32.dtsi
index b0b2b57..e441033 100644
--- a/arch/arm/dts/uniphier-common32.dtsi
+++ b/arch/arm/dts/uniphier-common32.dtsi
@@ -31,7 +31,7 @@
 			interrupts = <0 33 4>;
 			pinctrl-names = "default";
 			pinctrl-0 = <&pinctrl_uart0>;
-			clocks = <&uart_clk>;
+			clocks = <&peri_clk 0>;
 		};
 
 		serial1: serial@54006900 {
@@ -41,7 +41,7 @@
 			interrupts = <0 35 4>;
 			pinctrl-names = "default";
 			pinctrl-0 = <&pinctrl_uart1>;
-			clocks = <&uart_clk>;
+			clocks = <&peri_clk 1>;
 		};
 
 		serial2: serial@54006a00 {
@@ -51,7 +51,7 @@
 			interrupts = <0 37 4>;
 			pinctrl-names = "default";
 			pinctrl-0 = <&pinctrl_uart2>;
-			clocks = <&uart_clk>;
+			clocks = <&peri_clk 2>;
 		};
 
 		serial3: serial@54006b00 {
@@ -61,7 +61,7 @@
 			interrupts = <0 177 4>;
 			pinctrl-names = "default";
 			pinctrl-0 = <&pinctrl_uart3>;
-			clocks = <&uart_clk>;
+			clocks = <&peri_clk 3>;
 		};
 
 		system_bus: system-bus@58c00000 {
@@ -79,16 +79,33 @@
 			reg = <0x59801000 0x400>;
 		};
 
-		mio: mioctrl@59810000 {
-			/* specify compatible in each SoC DTSI */
+		mioctrl@59810000 {
+			compatible = "socionext,uniphier-mioctrl",
+				     "simple-mfd", "syscon";
 			reg = <0x59810000 0x800>;
-			#clock-cells = <1>;
+			u-boot,dm-pre-reloc;
+
+			mio_clk: clock {
+				#clock-cells = <1>;
+			};
+
+			mio_rst: reset {
+				#reset-cells = <1>;
+			};
 		};
 
-		peri: perictrl@59820000 {
-			/* specify compatible in each SoC DTSI */
+		perictrl@59820000 {
+			compatible = "socionext,uniphier-perictrl",
+				     "simple-mfd", "syscon";
 			reg = <0x59820000 0x200>;
-			#clock-cells = <1>;
+
+			peri_clk: clock {
+				#clock-cells = <1>;
+			};
+
+			peri_rst: reset {
+				#reset-cells = <1>;
+			};
 		};
 
 		timer@60000200 {
@@ -114,7 +131,8 @@
 		};
 
 		soc-glue@5f800000 {
-			compatible = "simple-mfd", "syscon";
+			compatible = "socionext,uniphier-soc-glue",
+				     "simple-mfd", "syscon";
 			reg = <0x5f800000 0x2000>;
 			u-boot,dm-pre-reloc;
 
@@ -124,12 +142,18 @@
 			};
 		};
 
-		sysctrl: sysctrl@61840000 {
-			/* specify compatible in each SoC DTSI */
+		sysctrl@61840000 {
+			compatible = "socionext,uniphier-sysctrl",
+				     "simple-mfd", "syscon";
 			reg = <0x61840000 0x4000>;
-			#clock-cells = <1>;
-			clock-names = "ref";
-			clocks = <&refclk>;
+
+			sys_clk: clock {
+				#clock-cells = <1>;
+			};
+
+			sys_rst: reset {
+				#reset-cells = <1>;
+			};
 		};
 
 		nand: nand@68000000 {
diff --git a/arch/arm/dts/uniphier-ph1-ld11.dtsi b/arch/arm/dts/uniphier-ph1-ld11.dtsi
index ffe04f5..0bdbbdd 100644
--- a/arch/arm/dts/uniphier-ph1-ld11.dtsi
+++ b/arch/arm/dts/uniphier-ph1-ld11.dtsi
@@ -54,12 +54,6 @@
 			clock-frequency = <25000000>;
 		};
 
-		uart_clk: uart_clk {
-			#clock-cells = <0>;
-			compatible = "fixed-clock";
-			clock-frequency = <58820000>;
-		};
-
 		i2c_clk: i2c_clk {
 			#clock-cells = <0>;
 			compatible = "fixed-clock";
@@ -69,10 +63,10 @@
 
 	timer {
 		compatible = "arm,armv8-timer";
-		interrupts = <1 13 0xf01>,
-			     <1 14 0xf01>,
-			     <1 11 0xf01>,
-			     <1 10 0xf01>;
+		interrupts = <1 13 4>,
+			     <1 14 4>,
+			     <1 11 4>,
+			     <1 10 4>;
 	};
 
 	soc {
@@ -89,7 +83,7 @@
 			interrupts = <0 33 4>;
 			pinctrl-names = "default";
 			pinctrl-0 = <&pinctrl_uart0>;
-			clocks = <&uart_clk>;
+			clocks = <&peri_clk 0>;
 			clock-frequency = <58820000>;
 		};
 
@@ -100,7 +94,7 @@
 			interrupts = <0 35 4>;
 			pinctrl-names = "default";
 			pinctrl-0 = <&pinctrl_uart1>;
-			clocks = <&uart_clk>;
+			clocks = <&peri_clk 1>;
 			clock-frequency = <58820000>;
 		};
 
@@ -111,7 +105,7 @@
 			interrupts = <0 37 4>;
 			pinctrl-names = "default";
 			pinctrl-0 = <&pinctrl_uart2>;
-			clocks = <&uart_clk>;
+			clocks = <&peri_clk 2>;
 			clock-frequency = <58820000>;
 		};
 
@@ -122,7 +116,7 @@
 			interrupts = <0 177 4>;
 			pinctrl-names = "default";
 			pinctrl-0 = <&pinctrl_uart3>;
-			clocks = <&uart_clk>;
+			clocks = <&peri_clk 3>;
 			clock-frequency = <58820000>;
 		};
 
@@ -213,6 +207,22 @@
 			reg = <0x59801000 0x400>;
 		};
 
+		perictrl@59820000 {
+			compatible = "socionext,uniphier-perictrl",
+				     "simple-mfd", "syscon";
+			reg = <0x59820000 0x200>;
+
+			peri_clk: clock {
+				compatible = "socionext,uniphier-ld11-peri-clock";
+				#clock-cells = <1>;
+			};
+
+			peri_rst: reset {
+				compatible = "socionext,uniphier-ld11-peri-reset";
+				#reset-cells = <1>;
+			};
+		};
+
 		usb0: usb@5a800100 {
 			compatible = "socionext,uniphier-ehci", "generic-ehci";
 			status = "disabled";
@@ -220,7 +230,7 @@
 			interrupts = <0 243 4>;
 			pinctrl-names = "default";
 			pinctrl-0 = <&pinctrl_usb0>;
-			clocks = <&mio 3>, <&mio 6>;
+			clocks = <&mio_clk 3>, <&mio_clk 6>;
 		};
 
 		usb1: usb@5a810100 {
@@ -230,7 +240,7 @@
 			interrupts = <0 244 4>;
 			pinctrl-names = "default";
 			pinctrl-0 = <&pinctrl_usb1>;
-			clocks = <&mio 4>, <&mio 6>;
+			clocks = <&mio_clk 4>, <&mio_clk 6>;
 		};
 
 		usb2: usb@5a820100 {
@@ -240,17 +250,29 @@
 			interrupts = <0 245 4>;
 			pinctrl-names = "default";
 			pinctrl-0 = <&pinctrl_usb2>;
-			clocks = <&mio 5>, <&mio 6>;
+			clocks = <&mio_clk 5>, <&mio_clk 6>;
 		};
 
-		mio: mioctrl@5b3e0000 {
-			compatible = "socionext,ph1-ld11-mioctrl";
+		mioctrl@5b3e0000 {
+			compatible = "socionext,uniphier-mioctrl",
+				     "simple-mfd", "syscon";
 			reg = <0x5b3e0000 0x800>;
-			#clock-cells = <1>;
+
+			mio_clk: clock {
+				compatible = "socionext,uniphier-ld11-mio-clock";
+				#clock-cells = <1>;
+			};
+
+			mio_rst: reset {
+				compatible = "socionext,uniphier-ld11-mio-reset";
+				#reset-cells = <1>;
+				resets = <&sys_rst 7>;
+			};
 		};
 
 		soc-glue@5f800000 {
-			compatible = "simple-mfd", "syscon";
+			compatible = "socionext,uniphier-soc-glue",
+				     "simple-mfd", "syscon";
 			reg = <0x5f800000 0x2000>;
 			u-boot,dm-pre-reloc;
 
@@ -273,6 +295,22 @@
 			#interrupt-cells = <3>;
 			interrupts = <1 9 4>;
 		};
+
+		sysctrl@61840000 {
+			compatible = "socionext,uniphier-ld11-sysctrl",
+				     "simple-mfd", "syscon";
+			reg = <0x61840000 0x4000>;
+
+			sys_clk: clock {
+				compatible = "socionext,uniphier-ld11-clock";
+				#clock-cells = <1>;
+			};
+
+			sys_rst: reset {
+				compatible = "socionext,uniphier-ld11-reset";
+				#reset-cells = <1>;
+			};
+		};
 	};
 };
 
diff --git a/arch/arm/dts/uniphier-ph1-ld20.dtsi b/arch/arm/dts/uniphier-ph1-ld20.dtsi
index 7497539..7f97f88 100644
--- a/arch/arm/dts/uniphier-ph1-ld20.dtsi
+++ b/arch/arm/dts/uniphier-ph1-ld20.dtsi
@@ -78,12 +78,6 @@
 			clock-frequency = <25000000>;
 		};
 
-		uart_clk: uart_clk {
-			#clock-cells = <0>;
-			compatible = "fixed-clock";
-			clock-frequency = <58820000>;
-		};
-
 		i2c_clk: i2c_clk {
 			#clock-cells = <0>;
 			compatible = "fixed-clock";
@@ -93,10 +87,10 @@
 
 	timer {
 		compatible = "arm,armv8-timer";
-		interrupts = <1 13 0xf01>,
-			     <1 14 0xf01>,
-			     <1 11 0xf01>,
-			     <1 10 0xf01>;
+		interrupts = <1 13 4>,
+			     <1 14 4>,
+			     <1 11 4>,
+			     <1 10 4>;
 	};
 
 	soc {
@@ -113,7 +107,7 @@
 			interrupts = <0 33 4>;
 			pinctrl-names = "default";
 			pinctrl-0 = <&pinctrl_uart0>;
-			clocks = <&uart_clk>;
+			clocks = <&peri_clk 0>;
 			clock-frequency = <58820000>;
 		};
 
@@ -124,7 +118,7 @@
 			interrupts = <0 35 4>;
 			pinctrl-names = "default";
 			pinctrl-0 = <&pinctrl_uart1>;
-			clocks = <&uart_clk>;
+			clocks = <&peri_clk 1>;
 			clock-frequency = <58820000>;
 		};
 
@@ -135,7 +129,7 @@
 			interrupts = <0 37 4>;
 			pinctrl-names = "default";
 			pinctrl-0 = <&pinctrl_uart2>;
-			clocks = <&uart_clk>;
+			clocks = <&peri_clk 2>;
 			clock-frequency = <58820000>;
 		};
 
@@ -146,7 +140,7 @@
 			interrupts = <0 177 4>;
 			pinctrl-names = "default";
 			pinctrl-0 = <&pinctrl_uart3>;
-			clocks = <&uart_clk>;
+			clocks = <&peri_clk 3>;
 			clock-frequency = <58820000>;
 		};
 
@@ -237,10 +231,36 @@
 			reg = <0x59801000 0x400>;
 		};
 
-		mio: mioctrl@59810000 {
-			compatible = "socionext,ph1-ld20-mioctrl";
+		mioctrl@59810000 {
+			compatible = "socionext,uniphier-mioctrl",
+				     "simple-mfd", "syscon";
 			reg = <0x59810000 0x800>;
-			#clock-cells = <1>;
+
+			mio_clk: clock {
+				compatible = "socionext,uniphier-ld20-mio-clock";
+				#clock-cells = <1>;
+			};
+
+			mio_rst: reset {
+				compatible = "socionext,uniphier-ld20-mio-reset";
+				#reset-cells = <1>;
+			};
+		};
+
+		perictrl@59820000 {
+			compatible = "socionext,uniphier-perictrl",
+				     "simple-mfd", "syscon";
+			reg = <0x59820000 0x200>;
+
+			peri_clk: clock {
+				compatible = "socionext,uniphier-ld20-peri-clock";
+				#clock-cells = <1>;
+			};
+
+			peri_rst: reset {
+				compatible = "socionext,uniphier-ld20-peri-reset";
+				#reset-cells = <1>;
+			};
 		};
 
 		sd: sdhc@5a400000 {
@@ -250,12 +270,13 @@
 			interrupts = <0 76 4>;
 			pinctrl-names = "default";
 			pinctrl-0 = <&pinctrl_sd>;
-			clocks = <&mio 0>;
+			clocks = <&mio_clk 0>;
 			bus-width = <4>;
 		};
 
 		soc-glue@5f800000 {
-			compatible = "simple-mfd", "syscon";
+			compatible = "socionext,uniphier-soc-glue",
+				     "simple-mfd", "syscon";
 			reg = <0x5f800000 0x2000>;
 			u-boot,dm-pre-reloc;
 
@@ -278,6 +299,22 @@
 			#interrupt-cells = <3>;
 			interrupts = <1 9 4>;
 		};
+
+		sysctrl@61840000 {
+			compatible = "socionext,uniphier-sysctrl",
+				     "simple-mfd", "syscon";
+			reg = <0x61840000 0x4000>;
+
+			sys_clk: clock {
+				compatible = "socionext,uniphier-ld20-clock";
+				#clock-cells = <1>;
+			};
+
+			sys_rst: reset {
+				compatible = "socionext,uniphier-ld20-reset";
+				#reset-cells = <1>;
+			};
+		};
 	};
 };
 
diff --git a/arch/arm/dts/uniphier-ph1-ld4.dtsi b/arch/arm/dts/uniphier-ph1-ld4.dtsi
index 07f315a..e4884b9 100644
--- a/arch/arm/dts/uniphier-ph1-ld4.dtsi
+++ b/arch/arm/dts/uniphier-ph1-ld4.dtsi
@@ -30,12 +30,6 @@
 			clock-frequency = <50000000>;
 		};
 
-		uart_clk: uart_clk {
-			#clock-cells = <0>;
-			compatible = "fixed-clock";
-			clock-frequency = <36864000>;
-		};
-
 		iobus_clk: iobus_clk {
 			#clock-cells = <0>;
 			compatible = "fixed-clock";
@@ -228,7 +222,7 @@
 		pinctrl-names = "default", "1.8v";
 		pinctrl-0 = <&pinctrl_sd>;
 		pinctrl-1 = <&pinctrl_sd_1v8>;
-		clocks = <&mio 0>;
+		clocks = <&mio_clk 0>;
 		bus-width = <4>;
 	};
 
@@ -240,7 +234,7 @@
 		pinctrl-names = "default", "1.8v";
 		pinctrl-0 = <&pinctrl_emmc>;
 		pinctrl-1 = <&pinctrl_emmc_1v8>;
-		clocks = <&mio 1>;
+		clocks = <&mio_clk 1>;
 		bus-width = <8>;
 		non-removable;
 	};
@@ -252,7 +246,7 @@
 		interrupts = <0 80 4>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&pinctrl_usb0>;
-		clocks = <&mio 3>, <&mio 6>;
+		clocks = <&mio_clk 3>, <&mio_clk 6>;
 	};
 
 	usb1: usb@5a810100 {
@@ -262,7 +256,7 @@
 		interrupts = <0 81 4>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&pinctrl_usb1>;
-		clocks = <&mio 4>, <&mio 6>;
+		clocks = <&mio_clk 4>, <&mio_clk 6>;
 	};
 
 	usb2: usb@5a820100 {
@@ -272,7 +266,7 @@
 		interrupts = <0 82 4>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&pinctrl_usb2>;
-		clocks = <&mio 5>, <&mio 6>;
+		clocks = <&mio_clk 5>, <&mio_clk 6>;
 	};
 
 	aidet@61830000 {
@@ -302,22 +296,30 @@
 	clock-frequency = <36864000>;
 };
 
+&mio_clk {
+	compatible = "socionext,uniphier-ld4-mio-clock";
+};
+
+&mio_rst {
+	compatible = "socionext,uniphier-ld4-mio-reset";
+};
+
-&mio {
-	compatible = "socionext,ph1-ld4-mioctrl";
-	clock-names = "stdmac", "ehci";
-	clocks = <&sysctrl 10>, <&sysctrl 18>;
+&peri_clk {
+	compatible = "socionext,uniphier-ld4-peri-clock";
 };
 
-&peri {
-	compatible = "socionext,ph1-ld4-perictrl";
-	clock-names = "uart", "i2c";
-	clocks = <&sysctrl 3>, <&sysctrl 4>;
+&peri_rst {
+	compatible = "socionext,uniphier-ld4-peri-reset";
 };
 
 &pinctrl {
 	compatible = "socionext,uniphier-ld4-pinctrl";
 };
 
-&sysctrl {
-	compatible = "socionext,ph1-ld4-sysctrl";
+&sys_clk {
+	compatible = "socionext,uniphier-ld4-clock";
+};
+
+&sys_rst {
+	compatible = "socionext,uniphier-ld4-reset";
 };
diff --git a/arch/arm/dts/uniphier-ph1-pro4-sanji.dts b/arch/arm/dts/uniphier-ph1-pro4-sanji.dts
index 965fe08..3f178d2 100644
--- a/arch/arm/dts/uniphier-ph1-pro4-sanji.dts
+++ b/arch/arm/dts/uniphier-ph1-pro4-sanji.dts
@@ -89,7 +89,7 @@
 	u-boot,dm-pre-reloc;
 };
 
-&mio {
+&mio_clk {
 	u-boot,dm-pre-reloc;
 };
 
diff --git a/arch/arm/dts/uniphier-ph1-pro4.dtsi b/arch/arm/dts/uniphier-ph1-pro4.dtsi
index e0b28b8..192ce84 100644
--- a/arch/arm/dts/uniphier-ph1-pro4.dtsi
+++ b/arch/arm/dts/uniphier-ph1-pro4.dtsi
@@ -351,7 +351,7 @@
 		pinctrl-names = "default", "1.8v";
 		pinctrl-0 = <&pinctrl_sd>;
 		pinctrl-1 = <&pinctrl_sd_1v8>;
-		clocks = <&mio 0>;
+		clocks = <&mio_clk 0>;
 		bus-width = <4>;
 	};
 
@@ -363,7 +363,7 @@
 		pinctrl-names = "default", "1.8v";
 		pinctrl-0 = <&pinctrl_emmc>;
 		pinctrl-1 = <&pinctrl_emmc_1v8>;
-		clocks = <&mio 1>;
+		clocks = <&mio_clk 1>;
 		bus-width = <8>;
 		non-removable;
 	};
@@ -376,7 +376,7 @@
 		pinctrl-names = "default", "1.8v";
 		pinctrl-0 = <&pinctrl_sd1>;
 		pinctrl-1 = <&pinctrl_sd1_1v8>;
-		clocks = <&mio 2>;
+		clocks = <&mio_clk 2>;
 		bus-width = <4>;
 	};
 
@@ -387,7 +387,7 @@
 		interrupts = <0 80 4>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&pinctrl_usb2>;
-		clocks = <&mio 3>, <&mio 6>;
+		clocks = <&mio_clk 3>, <&mio_clk 6>;
 	};
 
 	usb3: usb@5a810100 {
@@ -397,7 +397,7 @@
 		interrupts = <0 81 4>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&pinctrl_usb3>;
-		clocks = <&mio 4>, <&mio 6>;
+		clocks = <&mio_clk 4>, <&mio_clk 6>;
 	};
 
 	aidet@5fc20000 {
@@ -444,22 +444,30 @@
 	clock-frequency = <73728000>;
 };
 
-&mio {
-	compatible = "socionext,ph1-pro4-mioctrl";
-	clock-names = "stdmac", "ehci";
-	clocks = <&sysctrl 10>, <&sysctrl 18>;
+&mio_clk {
+	compatible = "socionext,uniphier-pro4-mio-clock";
 };
 
-&peri {
-	compatible = "socionext,ph1-pro4-perictrl";
-	clock-names = "uart", "fi2c";
-	clocks = <&sysctrl 3>, <&sysctrl 4>;
+&mio_rst {
+	compatible = "socionext,uniphier-pro4-mio-reset";
 };
 
+&peri_clk {
+	compatible = "socionext,uniphier-pro4-peri-clock";
+};
+
+&peri_rst {
+	compatible = "socionext,uniphier-pro4-peri-reset";
+};
+
 &pinctrl {
 	compatible = "socionext,uniphier-pro4-pinctrl";
 };
 
+&sys_clk {
+	compatible = "socionext,uniphier-pro4-clock";
+};
+
-&sysctrl {
-	compatible = "socionext,ph1-pro4-sysctrl";
+&sys_rst {
+	compatible = "socionext,uniphier-pro4-reset";
 };
diff --git a/arch/arm/dts/uniphier-ph1-pro5.dtsi b/arch/arm/dts/uniphier-ph1-pro5.dtsi
index 05f961f..22a70b1 100644
--- a/arch/arm/dts/uniphier-ph1-pro5.dtsi
+++ b/arch/arm/dts/uniphier-ph1-pro5.dtsi
@@ -38,12 +38,6 @@
 			clock-frequency = <50000000>;
 		};
 
-		uart_clk: uart_clk {
-			#clock-cells = <0>;
-			compatible = "fixed-clock";
-			clock-frequency = <73728000>;
-		};
-
 		i2c_clk: i2c_clk {
 			#clock-cells = <0>;
 			compatible = "fixed-clock";
@@ -367,7 +361,7 @@
 		interrupts = <0 78 4>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&pinctrl_emmc>;
-		clocks = <&mio 1>;
+		clocks = <&mio_clk 1>;
 		bus-width = <8>;
 		non-removable;
 	};
@@ -380,7 +374,7 @@
 		pinctrl-names = "default", "1.8v";
 		pinctrl-0 = <&pinctrl_sd>;
 		pinctrl-1 = <&pinctrl_sd_1v8>;
-		clocks = <&mio 0>;
+		clocks = <&mio_clk 0>;
 		bus-width = <4>;
 	};
 
@@ -423,22 +417,30 @@
 	clock-frequency = <73728000>;
 };
 
+&mio_clk {
+	compatible = "socionext,uniphier-pro5-mio-clock";
+};
+
+&mio_rst {
+	compatible = "socionext,uniphier-pro5-mio-reset";
+};
+
-&mio {
-	compatible = "socionext,ph1-pro5-mioctrl";
-	clock-names = "stdmac";
-	clocks = <&sysctrl 10>;
+&peri_clk {
+	compatible = "socionext,uniphier-pro5-peri-clock";
 };
 
-&peri {
-	compatible = "socionext,ph1-pro5-perictrl";
-	clock-names = "uart", "fi2c";
-	clocks = <&sysctrl 3>, <&sysctrl 4>;
+&peri_rst {
+	compatible = "socionext,uniphier-pro5-peri-reset";
 };
 
 &pinctrl {
 	compatible = "socionext,uniphier-pro5-pinctrl";
 };
 
-&sysctrl {
-	compatible = "socionext,ph1-pro5-sysctrl";
+&sys_clk {
+	compatible = "socionext,uniphier-pro5-clock";
+};
+
+&sys_rst {
+	compatible = "socionext,uniphier-pro5-reset";
 };
diff --git a/arch/arm/dts/uniphier-ph1-sld3-ref.dts b/arch/arm/dts/uniphier-ph1-sld3-ref.dts
index f3e76b3..116e571 100644
--- a/arch/arm/dts/uniphier-ph1-sld3-ref.dts
+++ b/arch/arm/dts/uniphier-ph1-sld3-ref.dts
@@ -86,10 +86,6 @@
        u-boot,dm-pre-reloc;
 };
 
-&mio {
-       u-boot,dm-pre-reloc;
-};
-
 &emmc {
        u-boot,dm-pre-reloc;
 };
diff --git a/arch/arm/dts/uniphier-ph1-sld3.dtsi b/arch/arm/dts/uniphier-ph1-sld3.dtsi
index d8c44b7..a554b08 100644
--- a/arch/arm/dts/uniphier-ph1-sld3.dtsi
+++ b/arch/arm/dts/uniphier-ph1-sld3.dtsi
@@ -42,12 +42,6 @@
 			clock-frequency = <50000000>;
 		};
 
-		uart_clk: uart_clk {
-			#clock-cells = <0>;
-			compatible = "fixed-clock";
-			clock-frequency = <36864000>;
-		};
-
 		iobus_clk: iobus_clk {
 			#clock-cells = <0>;
 			compatible = "fixed-clock";
@@ -92,7 +86,6 @@
 			interrupts = <0 33 4>;
 			pinctrl-names = "default";
 			pinctrl-0 = <&pinctrl_uart0>;
-			clocks = <&uart_clk>;
 			clock-frequency = <36864000>;
 		};
 
@@ -103,7 +96,6 @@
 			interrupts = <0 35 4>;
 			pinctrl-names = "default";
 			pinctrl-0 = <&pinctrl_uart1>;
-			clocks = <&uart_clk>;
 			clock-frequency = <36864000>;
 		};
 
@@ -114,7 +106,6 @@
 			interrupts = <0 37 4>;
 			pinctrl-names = "default";
 			pinctrl-0 = <&pinctrl_uart2>;
-			clocks = <&uart_clk>;
 			clock-frequency = <36864000>;
 		};
 
@@ -299,12 +290,22 @@
 			reg = <0x59801000 0x400>;
 		};
 
-		mio: mioctrl@59810000 {
-			compatible = "socionext,ph1-sld3-mioctrl";
+		mioctrl@59810000 {
+			compatible = "socionext,uniphier-mioctrl",
+				     "simple-mfd", "syscon";
 			reg = <0x59810000 0x800>;
-			#clock-cells = <1>;
-			clock-names = "stdmac", "ehci";
-			clocks = <&sysctrl 10>, <&sysctrl 18>;
+			u-boot,dm-pre-reloc;
+
+			mio_clk: clock {
+				compatible = "socionext,uniphier-sld3-mio-clock";
+				#clock-cells = <1>;
+				u-boot,dm-pre-reloc;
+			};
+
+			mio_rst: reset {
+				compatible = "socionext,uniphier-sld3-mio-reset";
+				#reset-cells = <1>;
+			};
 		};
 
 		emmc: sdhc@5a400000 {
@@ -315,7 +316,7 @@
 			pinctrl-names = "default", "1.8v";
 			pinctrl-0 = <&pinctrl_emmc>;
 			pinctrl-1 = <&pinctrl_emmc_1v8>;
-			clocks = <&mio 1>;
+			clocks = <&mio_clk 1>;
 			bus-width = <8>;
 			non-removable;
 		};
@@ -328,7 +329,7 @@
 			pinctrl-names = "default", "1.8v";
 			pinctrl-0 = <&pinctrl_sd>;
 			pinctrl-1 = <&pinctrl_sd_1v8>;
-			clocks = <&mio 0>;
+			clocks = <&mio_clk 0>;
 			bus-width = <4>;
 		};
 
@@ -339,7 +340,7 @@
 			interrupts = <0 80 4>;
 			pinctrl-names = "default";
 			pinctrl-0 = <&pinctrl_usb0>;
-			clocks = <&mio 3>, <&mio 6>;
+			clocks = <&mio_clk 3>, <&mio_clk 6>;
 		};
 
 		usb1: usb@5a810100 {
@@ -349,7 +350,7 @@
 			interrupts = <0 81 4>;
 			pinctrl-names = "default";
 			pinctrl-0 = <&pinctrl_usb1>;
-			clocks = <&mio 4>, <&mio 6>;
+			clocks = <&mio_clk 4>, <&mio_clk 6>;
 		};
 
 		usb2: usb@5a820100 {
@@ -359,7 +360,7 @@
 			interrupts = <0 82 4>;
 			pinctrl-names = "default";
 			pinctrl-0 = <&pinctrl_usb2>;
-			clocks = <&mio 5>, <&mio 6>;
+			clocks = <&mio_clk 5>, <&mio_clk 6>;
 		};
 
 		usb3: usb@5a830100 {
@@ -369,7 +370,7 @@
 			interrupts = <0 83 4>;
 			pinctrl-names = "default";
 			pinctrl-0 = <&pinctrl_usb3>;
-			clocks = <&mio 7>, <&mio 6>;
+			clocks = <&mio_clk 7>, <&mio_clk 6>;
 		};
 
 		soc-glue@5f800000 {
@@ -388,12 +389,20 @@
 			reg = <0xf1830000 0x200>;
 		};
 
-		sysctrl: sysctrl@f1840000 {
-			compatible = "socionext,ph1-sld3-sysctrl";
+		sysctrl@f1840000 {
+			compatible = "socionext,uniphier-sysctrl",
+				     "simple-mfd", "syscon";
 			reg = <0xf1840000 0x4000>;
-			#clock-cells = <1>;
-			clock-names = "ref";
-			clocks = <&refclk>;
+
+			sys_clk: clock {
+				compatible = "socionext,uniphier-sld3-clock";
+				#clock-cells = <1>;
+			};
+
+			sys_rst: reset {
+				compatible = "socionext,uniphier-sld3-reset";
+				#reset-cells = <1>;
+			};
 		};
 
 		nand: nand@f8000000 {
diff --git a/arch/arm/dts/uniphier-ph1-sld8.dtsi b/arch/arm/dts/uniphier-ph1-sld8.dtsi
index e0376a1..1ecce50 100644
--- a/arch/arm/dts/uniphier-ph1-sld8.dtsi
+++ b/arch/arm/dts/uniphier-ph1-sld8.dtsi
@@ -30,12 +30,6 @@
 			clock-frequency = <50000000>;
 		};
 
-		uart_clk: uart_clk {
-			#clock-cells = <0>;
-			compatible = "fixed-clock";
-			clock-frequency = <80000000>;
-		};
-
 		iobus_clk: iobus_clk {
 			#clock-cells = <0>;
 			compatible = "fixed-clock";
@@ -228,7 +222,7 @@
 		pinctrl-names = "default", "1.8v";
 		pinctrl-0 = <&pinctrl_sd>;
 		pinctrl-1 = <&pinctrl_sd_1v8>;
-		clocks = <&mio 0>;
+		clocks = <&mio_clk 0>;
 		bus-width = <4>;
 	};
 
@@ -240,7 +234,7 @@
 		pinctrl-names = "default", "1.8v";
 		pinctrl-0 = <&pinctrl_emmc>;
 		pinctrl-1 = <&pinctrl_emmc_1v8>;
-		clocks = <&mio 1>;
+		clocks = <&mio_clk 1>;
 		bus-width = <8>;
 		non-removable;
 	};
@@ -252,7 +246,7 @@
 		interrupts = <0 80 4>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&pinctrl_usb0>;
-		clocks = <&mio 3>, <&mio 6>;
+		clocks = <&mio_clk 3>, <&mio_clk 6>;
 	};
 
 	usb1: usb@5a810100 {
@@ -262,7 +256,7 @@
 		interrupts = <0 81 4>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&pinctrl_usb1>;
-		clocks = <&mio 4>, <&mio 6>;
+		clocks = <&mio_clk 4>, <&mio_clk 6>;
 	};
 
 	usb2: usb@5a820100 {
@@ -272,7 +266,7 @@
 		interrupts = <0 82 4>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&pinctrl_usb2>;
-		clocks = <&mio 5>, <&mio 6>;
+		clocks = <&mio_clk 5>, <&mio_clk 6>;
 	};
 
 	aidet@61830000 {
@@ -302,22 +296,30 @@
 	clock-frequency = <80000000>;
 };
 
+&mio_clk {
+	compatible = "socionext,uniphier-sld8-mio-clock";
+};
+
+&mio_rst {
+	compatible = "socionext,uniphier-sld8-mio-reset";
+};
+
-&mio {
-	compatible = "socionext,ph1-sld8-mioctrl";
-	clock-names = "stdmac", "ehci";
-	clocks = <&sysctrl 10>, <&sysctrl 18>;
+&peri_clk {
+	compatible = "socionext,uniphier-sld8-peri-clock";
 };
 
-&peri {
-	compatible = "socionext,ph1-sld8-perictrl";
-	clock-names = "uart", "i2c";
-	clocks = <&sysctrl 3>, <&sysctrl 4>;
+&peri_rst {
+	compatible = "socionext,uniphier-sld8-peri-reset";
 };
 
 &pinctrl {
 	compatible = "socionext,uniphier-sld8-pinctrl";
 };
 
-&sysctrl {
-	compatible = "socionext,ph1-sld8-sysctrl";
+&sys_clk {
+	compatible = "socionext,uniphier-sld8-clock";
+};
+
+&sys_rst {
+	compatible = "socionext,uniphier-sld8-reset";
 };
diff --git a/arch/arm/dts/uniphier-proxstream2-gentil.dts b/arch/arm/dts/uniphier-proxstream2-gentil.dts
index 1175703..7233dc6 100644
--- a/arch/arm/dts/uniphier-proxstream2-gentil.dts
+++ b/arch/arm/dts/uniphier-proxstream2-gentil.dts
@@ -69,7 +69,7 @@
 	u-boot,dm-pre-reloc;
 };
 
-&mio {
+&mio_clk {
 	u-boot,dm-pre-reloc;
 };
 
diff --git a/arch/arm/dts/uniphier-proxstream2-vodka.dts b/arch/arm/dts/uniphier-proxstream2-vodka.dts
index 928a092..30ea270 100644
--- a/arch/arm/dts/uniphier-proxstream2-vodka.dts
+++ b/arch/arm/dts/uniphier-proxstream2-vodka.dts
@@ -54,7 +54,7 @@
 	u-boot,dm-pre-reloc;
 };
 
-&mio {
+&mio_clk {
 	u-boot,dm-pre-reloc;
 };
 
diff --git a/arch/arm/dts/uniphier-proxstream2.dtsi b/arch/arm/dts/uniphier-proxstream2.dtsi
index 23a6bfa..609cbaa 100644
--- a/arch/arm/dts/uniphier-proxstream2.dtsi
+++ b/arch/arm/dts/uniphier-proxstream2.dtsi
@@ -52,12 +52,6 @@
 			clock-frequency = <50000000>;
 		};
 
-		uart_clk: uart_clk {
-			#clock-cells = <0>;
-			compatible = "fixed-clock";
-			clock-frequency = <88900000>;
-		};
-
 		i2c_clk: i2c_clk {
 			#clock-cells = <0>;
 			compatible = "fixed-clock";
@@ -366,7 +360,7 @@
 		interrupts = <0 78 4>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&pinctrl_emmc>;
-		clocks = <&mio 1>;
+		clocks = <&mio_clk 1>;
 		bus-width = <8>;
 		non-removable;
 	};
@@ -379,7 +373,7 @@
 		pinctrl-names = "default", "1.8v";
 		pinctrl-0 = <&pinctrl_sd>;
 		pinctrl-1 = <&pinctrl_sd_1v8>;
-		clocks = <&mio 0>;
+		clocks = <&mio_clk 0>;
 		bus-width = <4>;
 	};
 
@@ -427,22 +421,30 @@
 	clock-frequency = <88900000>;
 };
 
+&mio_clk {
+	compatible = "socionext,uniphier-pxs2-mio-clock";
+};
+
+&mio_rst {
+	compatible = "socionext,uniphier-pxs2-mio-reset";
+};
+
-&mio {
-	compatible = "socionext,proxstream2-mioctrl";
-	clock-names = "stdmac";
-	clocks = <&sysctrl 10>;
+&peri_clk {
+	compatible = "socionext,uniphier-pxs2-peri-clock";
 };
 
-&peri {
-	compatible = "socionext,proxstream2-perictrl";
-	clock-names = "uart", "fi2c";
-	clocks = <&sysctrl 3>, <&sysctrl 4>;
+&peri_rst {
+	compatible = "socionext,uniphier-pxs2-peri-reset";
 };
 
 &pinctrl {
 	compatible = "socionext,uniphier-pxs2-pinctrl";
 };
 
-&sysctrl {
-	compatible = "socionext,proxstream2-sysctrl";
+&sys_clk {
+	compatible = "socionext,uniphier-pxs2-clock";
+};
+
+&sys_rst {
+	compatible = "socionext,uniphier-pxs2-reset";
 };
diff --git a/arch/arm/include/asm/arch-zynqmp/hardware.h b/arch/arm/include/asm/arch-zynqmp/hardware.h
index 35964d6..456c1b0 100644
--- a/arch/arm/include/asm/arch-zynqmp/hardware.h
+++ b/arch/arm/include/asm/arch-zynqmp/hardware.h
@@ -25,6 +25,13 @@
 
 #define ZYNQMP_CRL_APB_BASEADDR	0xFF5E0000
 #define ZYNQMP_CRL_APB_TIMESTAMP_REF_CTRL_CLKACT	0x1000000
+#define ZYNQMP_CRL_APB_BOOT_PIN_CTRL_OUT_EN_SHIFT	0
+#define ZYNQMP_CRL_APB_BOOT_PIN_CTRL_OUT_VAL_SHIFT	8
+
+#define PS_MODE0	BIT(0)
+#define PS_MODE1	BIT(1)
+#define PS_MODE2	BIT(2)
+#define PS_MODE3	BIT(3)
 
 struct crlapb_regs {
 	u32 reserved0[36];
@@ -35,7 +42,9 @@
 	u32 boot_mode; /* 0x200 */
 	u32 reserved3[14];
 	u32 rst_lpd_top; /* 0x23C */
-	u32 reserved4[26];
+	u32 reserved4[4];
+	u32 boot_pin_ctrl; /* 0x250 */
+	u32 reserved5[21];
 };
 
 #define crlapb_base ((struct crlapb_regs *)ZYNQMP_CRL_APB_BASEADDR)
@@ -69,7 +78,10 @@
 #define SD_MODE1	0x00000005 /* sd 1 */
 #define NAND_MODE	0x00000004
 #define EMMC_MODE	0x00000006
+#define USB_MODE	0x00000007
 #define JTAG_MODE	0x00000000
+#define BOOT_MODE_USE_ALT	0x100
+#define BOOT_MODE_ALT_SHIFT	12
 
 #define ZYNQMP_IOU_SLCR_BASEADDR	0xFF180000
 
diff --git a/arch/arm/include/asm/spl.h b/arch/arm/include/asm/spl.h
index 19c38f4..6f312d6 100644
--- a/arch/arm/include/asm/spl.h
+++ b/arch/arm/include/asm/spl.h
@@ -28,6 +28,7 @@
 	BOOT_DEVICE_SATA,
 	BOOT_DEVICE_I2C,
 	BOOT_DEVICE_BOARD,
+	BOOT_DEVICE_DFU,
 	BOOT_DEVICE_NONE
 };
 #endif
diff --git a/arch/arm/mach-uniphier/Kconfig b/arch/arm/mach-uniphier/Kconfig
index 2e824bb..7bee6c7 100644
--- a/arch/arm/mach-uniphier/Kconfig
+++ b/arch/arm/mach-uniphier/Kconfig
@@ -1,20 +1,5 @@
 if ARCH_UNIPHIER
 
-config SPL_LIBCOMMON_SUPPORT
-	default y
-
-config SPL_LIBGENERIC_SUPPORT
-	default y
-
-config SPL_MMC_SUPPORT
-	default y if !ARCH_UNIPHIER_64BIT
-
-config SPL_NAND_SUPPORT
-	default y if !ARM64
-
-config SPL_SERIAL_SUPPORT
-	default y
-
 config SYS_CONFIG_NAME
 	default "uniphier"
 
diff --git a/arch/arm/mach-uniphier/board_init.c b/arch/arm/mach-uniphier/board_init.c
index b57a33f..b9be52f 100644
--- a/arch/arm/mach-uniphier/board_init.c
+++ b/arch/arm/mach-uniphier/board_init.c
@@ -128,6 +128,7 @@
 		sg_set_pinsel(153, 14, 8, 4);	/* XIRQ4    -> XIRQ4 */
 		sg_set_iectrl(153);
 		led_puts("U1");
+		uniphier_ld11_pll_init();
 		uniphier_ld11_clk_init();
 		break;
 #endif
diff --git a/arch/arm/mach-uniphier/clk/Makefile b/arch/arm/mach-uniphier/clk/Makefile
index c8d59ea..95f433e 100644
--- a/arch/arm/mach-uniphier/clk/Makefile
+++ b/arch/arm/mach-uniphier/clk/Makefile
@@ -11,7 +11,7 @@
 obj-$(CONFIG_ARCH_UNIPHIER_PRO5)	+= early-clk-pro5.o
 obj-$(CONFIG_ARCH_UNIPHIER_PXS2)	+= early-clk-pxs2.o
 obj-$(CONFIG_ARCH_UNIPHIER_LD6B)	+= early-clk-pxs2.o
-obj-$(CONFIG_ARCH_UNIPHIER_LD11)	+= early-clk-ld11.o
+obj-$(CONFIG_ARCH_UNIPHIER_LD11)	+= early-clk-ld11.o dpll-ld11.o
 obj-$(CONFIG_ARCH_UNIPHIER_LD20)	+= early-clk-ld20.o dpll-ld20.o
 
 else
@@ -23,9 +23,10 @@
 obj-$(CONFIG_ARCH_UNIPHIER_PRO5)	+= clk-pro5.o
 obj-$(CONFIG_ARCH_UNIPHIER_PXS2)	+= clk-pxs2.o
 obj-$(CONFIG_ARCH_UNIPHIER_LD6B)	+= clk-pxs2.o
-obj-$(CONFIG_ARCH_UNIPHIER_LD11)	+= clk-ld11.o
+obj-$(CONFIG_ARCH_UNIPHIER_LD11)	+= clk-ld11.o pll-ld11.o
 obj-$(CONFIG_ARCH_UNIPHIER_LD20)	+= clk-ld20.o pll-ld20.o
 
 endif
 
+obj-$(CONFIG_ARCH_UNIPHIER_LD11)	+= pll-base-ld20.o
 obj-$(CONFIG_ARCH_UNIPHIER_LD20)	+= pll-base-ld20.o
diff --git a/arch/arm/mach-uniphier/clk/dpll-ld11.c b/arch/arm/mach-uniphier/clk/dpll-ld11.c
new file mode 100644
index 0000000..7f0677c
--- /dev/null
+++ b/arch/arm/mach-uniphier/clk/dpll-ld11.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include "../init.h"
+#include "../sc64-regs.h"
+#include "pll.h"
+
+int uniphier_ld11_dpll_init(const struct uniphier_board_data *bd)
+{
+	uniphier_ld20_sscpll_init(SC_DPLLCTRL, UNIPHIER_PLL_FREQ_DEFAULT, 0, 2);
+
+	return 0;
+}
diff --git a/arch/arm/mach-uniphier/clk/pll-ld11.c b/arch/arm/mach-uniphier/clk/pll-ld11.c
new file mode 100644
index 0000000..8a4a748
--- /dev/null
+++ b/arch/arm/mach-uniphier/clk/pll-ld11.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <linux/io.h>
+
+#include "../init.h"
+#include "../sc64-regs.h"
+#include "pll.h"
+
+void uniphier_ld11_pll_init(void)
+{
+	uniphier_ld20_sscpll_init(SC_CPLLCTRL, 1960, 1, 2);	/* 2000MHz -> 1960MHz */
+	/* do nothing for SPLL */
+	uniphier_ld20_sscpll_init(SC_MPLLCTRL, 1600, 1, 2);	/* 1500MHz -> 1600MHz */
+	uniphier_ld20_sscpll_init(SC_VSPLLCTRL, UNIPHIER_PLL_FREQ_DEFAULT, 0, 2);
+
+	mdelay(1);
+
+	uniphier_ld20_sscpll_ssc_en(SC_CPLLCTRL);
+	uniphier_ld20_sscpll_ssc_en(SC_MPLLCTRL);
+	uniphier_ld20_sscpll_ssc_en(SC_VSPLLCTRL);
+
+	uniphier_ld20_vpll27_init(SC_VPLL27FCTRL);
+	uniphier_ld20_vpll27_init(SC_VPLL27ACTRL);
+
+	writel(0, SC_CA53_GEARSET);	/* Gear0: CPLL/2 */
+	writel(SC_CA_GEARUPD, SC_CA53_GEARUPD);
+}
diff --git a/arch/arm/mach-uniphier/init.h b/arch/arm/mach-uniphier/init.h
index 5c7cd6b..4e3bee1 100644
--- a/arch/arm/mach-uniphier/init.h
+++ b/arch/arm/mach-uniphier/init.h
@@ -87,6 +87,7 @@
 int uniphier_ld4_dpll_init(const struct uniphier_board_data *bd);
 int uniphier_pro4_dpll_init(const struct uniphier_board_data *bd);
 int uniphier_sld8_dpll_init(const struct uniphier_board_data *bd);
+int uniphier_ld11_dpll_init(const struct uniphier_board_data *bd);
 int uniphier_ld20_dpll_init(const struct uniphier_board_data *bd);
 
 int uniphier_ld4_early_clk_init(const struct uniphier_board_data *bd);
@@ -105,6 +106,7 @@
 void uniphier_sld3_pll_init(void);
 void uniphier_ld4_pll_init(void);
 void uniphier_pro4_pll_init(void);
+void uniphier_ld11_pll_init(void);
 int uniphier_ld20_pll_init(const struct uniphier_board_data *bd);
 
 void uniphier_ld4_clk_init(void);
diff --git a/arch/arm/mach-uniphier/init/init-ld11.c b/arch/arm/mach-uniphier/init/init-ld11.c
index 758df8d..e324c94 100644
--- a/arch/arm/mach-uniphier/init/init-ld11.c
+++ b/arch/arm/mach-uniphier/init/init-ld11.c
@@ -31,12 +31,14 @@
 
 	led_puts("L2");
 
-	led_puts("L3");
-
 #ifdef CONFIG_SPL_SERIAL_SUPPORT
 	preloader_console_init();
 #endif
 
+	led_puts("L3");
+
+	uniphier_ld11_dpll_init(bd);
+
 	led_puts("L4");
 
 	{
diff --git a/arch/arm/mach-uniphier/sc64-regs.h b/arch/arm/mach-uniphier/sc64-regs.h
index 1e52bb1..780fdd1 100644
--- a/arch/arm/mach-uniphier/sc64-regs.h
+++ b/arch/arm/mach-uniphier/sc64-regs.h
@@ -13,12 +13,14 @@
 #define SC_BASE_ADDR		0x61840000
 
 /* PLL type: SSC */
-#define SC_CPLLCTRL	(SC_BASE_ADDR | 0x1400)	/* LD20: CPU/ARM */
-#define SC_SPLLCTRL	(SC_BASE_ADDR | 0x1410)	/* LD20: misc */
+#define SC_CPLLCTRL	(SC_BASE_ADDR | 0x1400)	/* LD11/20: CPU/ARM */
+#define SC_SPLLCTRL	(SC_BASE_ADDR | 0x1410)	/* LD11/20: misc */
 #define SC_SPLL2CTRL	(SC_BASE_ADDR | 0x1420)	/* LD20: IPP */
-#define SC_MPLLCTRL	(SC_BASE_ADDR | 0x1430)	/* LD20: Video codec */
+#define SC_MPLLCTRL	(SC_BASE_ADDR | 0x1430)	/* LD11/20: Video codec */
+#define SC_VSPLLCTRL	(SC_BASE_ADDR | 0x1440)	/* LD11 */
 #define SC_VPPLLCTRL	(SC_BASE_ADDR | 0x1440)	/* LD20: VPE etc. */
 #define SC_GPPLLCTRL	(SC_BASE_ADDR | 0x1450)	/* LD20: GPU/Mali */
+#define SC_DPLLCTRL	(SC_BASE_ADDR | 0x1460)	/* LD11: DDR memory */
 #define SC_DPLL0CTRL	(SC_BASE_ADDR | 0x1460)	/* LD20: DDR memory 0 */
 #define SC_DPLL1CTRL	(SC_BASE_ADDR | 0x1470)	/* LD20: DDR memory 1 */
 #define SC_DPLL2CTRL	(SC_BASE_ADDR | 0x1480)	/* LD20: DDR memory 2 */
@@ -61,4 +63,12 @@
 #define   SC_CLKCTRL7_UMC31		(1 << 1)
 #define   SC_CLKCTRL7_UMC30		(1 << 0)
 
+#define SC_CA72_GEARST		(SC_BASE_ADDR | 0x8080)
+#define SC_CA72_GEARSET		(SC_BASE_ADDR | 0x8084)
+#define SC_CA72_GEARUPD		(SC_BASE_ADDR | 0x8088)
+#define SC_CA53_GEARST		(SC_BASE_ADDR | 0x8080)
+#define SC_CA53_GEARSET		(SC_BASE_ADDR | 0x8084)
+#define SC_CA53_GEARUPD		(SC_BASE_ADDR | 0x8088)
+#define   SC_CA_GEARUPD			(1 << 0)
+
 #endif /* SC64_REGS_H */
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 21066f0..097ad58 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -26,6 +26,8 @@
 	select DM
 	select DM_SERIAL
 	select DYNAMIC_IO_PORT_BASE
+	select MIPS_CM
+	select MIPS_L2_CACHE
 	select OF_CONTROL
 	select OF_ISA_BUS
 	select SUPPORTS_BIG_ENDIAN
@@ -73,10 +75,43 @@
 	select OF_CONTROL
 	select DM
 
+config TARGET_BOSTON
+	bool "Support Boston"
+	select DM
+	select DM_SERIAL
+	select OF_CONTROL
+	select MIPS_CM
+	select MIPS_L1_CACHE_SHIFT_6
+	select MIPS_L2_CACHE
+	select SUPPORTS_BIG_ENDIAN
+	select SUPPORTS_LITTLE_ENDIAN
+	select SUPPORTS_CPU_MIPS32_R1
+	select SUPPORTS_CPU_MIPS32_R2
+	select SUPPORTS_CPU_MIPS32_R6
+	select SUPPORTS_CPU_MIPS64_R1
+	select SUPPORTS_CPU_MIPS64_R2
+	select SUPPORTS_CPU_MIPS64_R6
+
+config TARGET_XILFPGA
+	bool "Support Imagination Xilfpga"
+	select OF_CONTROL
+	select DM
+	select DM_SERIAL
+	select DM_GPIO
+	select DM_ETH
+	select SUPPORTS_LITTLE_ENDIAN
+	select SUPPORTS_CPU_MIPS32_R1
+	select SUPPORTS_CPU_MIPS32_R2
+	select MIPS_L1_CACHE_SHIFT_4
+	help
+	  This supports IMGTEC MIPSfpga platform
+
 endchoice
 
 source "board/dbau1x00/Kconfig"
+source "board/imgtec/boston/Kconfig"
 source "board/imgtec/malta/Kconfig"
+source "board/imgtec/xilfpga/Kconfig"
 source "board/micronas/vct/Kconfig"
 source "board/pb1x00/Kconfig"
 source "board/qemu-mips/Kconfig"
@@ -300,8 +335,30 @@
 	default "4" if MIPS_L1_CACHE_SHIFT_4
 	default "5"
 
+config MIPS_L2_CACHE
+	bool
+	help
+	  Select this if your system includes an L2 cache and you want U-Boot
+	  to initialise & maintain it.
+
 config DYNAMIC_IO_PORT_BASE
 	bool
+
+config MIPS_CM
+	bool
+	help
+	  Select this if your system contains a MIPS Coherence Manager and you
+	  wish U-Boot to configure it or make use of it to retrieve system
+	  information such as cache configuration.
+
+config MIPS_CM_BASE
+	hex
+	default 0x1fbf8000
+	help
+	  The physical base address at which to map the MIPS Coherence Manager
+	  Global Configuration Registers (GCRs). This should be set such that
+	  the GCRs occupy a region of the physical address space which is
+	  otherwise unused, or at minimum that software doesn't need to access.
 
 endif
 
diff --git a/arch/mips/cpu/Makefile b/arch/mips/cpu/Makefile
index fc6b455..429fd3a 100644
--- a/arch/mips/cpu/Makefile
+++ b/arch/mips/cpu/Makefile
@@ -7,3 +7,5 @@
 obj-y += time.o
 obj-y += interrupts.o
 obj-y += cpu.o
+
+obj-$(CONFIG_MIPS_CM)	+= cm_init.o
diff --git a/arch/mips/cpu/cm_init.S b/arch/mips/cpu/cm_init.S
new file mode 100644
index 0000000..ddcaa49
--- /dev/null
+++ b/arch/mips/cpu/cm_init.S
@@ -0,0 +1,45 @@
+/*
+ * MIPS Coherence Manager (CM) Initialisation
+ *
+ * Copyright (c) 2016 Imagination Technologies Ltd.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <asm/addrspace.h>
+#include <asm/asm.h>
+#include <asm/cm.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+
+LEAF(mips_cm_map)
+	/* Config3 must exist for a CM to be present */
+	mfc0		t0, CP0_CONFIG, 1
+	bgez		t0, 2f
+	mfc0		t0, CP0_CONFIG, 2
+	bgez		t0, 2f
+
+	/* Check Config3.CMGCR to determine CM presence */
+	mfc0		t0, CP0_CONFIG, 3
+	and		t0, t0, MIPS_CONF3_CMGCR
+	beqz		t0, 2f
+
+	/* Find the current physical GCR base address */
+1:	MFC0		t0, CP0_CMGCRBASE
+	PTR_SLL		t0, t0, 4
+
+	/* If the GCRs are where we want, we're done */
+	PTR_LI		t1, CONFIG_MIPS_CM_BASE
+	beq		t0, t1, 2f
+
+	/* Move the GCRs to our configured base address */
+	PTR_LI		t2, CKSEG1
+	PTR_ADDU	t0, t0, t2
+	sw		zero, GCR_BASE_UPPER(t0)
+	sw		t1, GCR_BASE(t0)
+
+	/* Re-check the GCR base */
+	b		1b
+
+2:	jr		ra
+	END(mips_cm_map)
diff --git a/arch/mips/cpu/cpu.c b/arch/mips/cpu/cpu.c
index 391feb3..1b919ed 100644
--- a/arch/mips/cpu/cpu.c
+++ b/arch/mips/cpu/cpu.c
@@ -8,6 +8,7 @@
 #include <common.h>
 #include <command.h>
 #include <linux/compiler.h>
+#include <asm/cache.h>
 #include <asm/mipsregs.h>
 #include <asm/reboot.h>
 
@@ -35,3 +36,9 @@
 	write_c0_index(index);
 	tlb_write_indexed();
 }
+
+int arch_cpu_init(void)
+{
+	mips_cache_probe();
+	return 0;
+}
diff --git a/arch/mips/cpu/start.S b/arch/mips/cpu/start.S
index fc6dd66..3f0fc12 100644
--- a/arch/mips/cpu/start.S
+++ b/arch/mips/cpu/start.S
@@ -12,10 +12,6 @@
 #include <asm/regdef.h>
 #include <asm/mipsregs.h>
 
-#ifndef CONFIG_SYS_MIPS_CACHE_MODE
-#define CONFIG_SYS_MIPS_CACHE_MODE CONF_CM_CACHABLE_NONCOHERENT
-#endif
-
 #ifndef CONFIG_SYS_INIT_SP_ADDR
 #define CONFIG_SYS_INIT_SP_ADDR	(CONFIG_SYS_SDRAM_BASE + \
 				CONFIG_SYS_INIT_SP_OFFSET)
@@ -112,9 +108,28 @@
 
 	.align 4
 reset:
+#if __mips_isa_rev >= 6
+	mfc0	t0, CP0_CONFIG, 5
+	and	t0, t0, MIPS_CONF5_VP
+	beqz	t0, 1f
+	 nop
+
+	b	2f
+	 mfc0	t0, CP0_GLOBALNUMBER
+#endif
+
+1:	mfc0	t0, CP0_EBASE
+	and	t0, t0, EBASE_CPUNUM
+
+	/* Hang if this isn't the first CPU in the system */
+2:	beqz	t0, 4f
+	 nop
+3:	wait
+	b	3b
+	 nop
 
 	/* Clear watch registers */
-	MTC0	zero, CP0_WATCHLO
+4:	MTC0	zero, CP0_WATCHLO
 	mtc0	zero, CP0_WATCHHI
 
 	/* WP(Watch Pending), SW0/1 should be cleared */
@@ -127,9 +142,11 @@
 	mtc0	zero, CP0_COMPARE
 
 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
-	/* CONFIG0 register */
-	li	t0, CONF_CM_UNCACHED
+	mfc0	t0, CP0_CONFIG
+	and	t0, t0, MIPS_CONF_IMPL
+	or	t0, t0, CONF_CM_UNCACHED
 	mtc0	t0, CP0_CONFIG
+	ehb
 #endif
 
 	/*
@@ -144,20 +161,31 @@
 1:
 	PTR_L	gp, 0(ra)
 
+#ifdef CONFIG_MIPS_CM
+	PTR_LA	t9, mips_cm_map
+	jalr	t9
+	 nop
+#endif
+
 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
+# ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD
 	/* Initialize any external memory */
 	PTR_LA	t9, lowlevel_init
 	jalr	t9
 	 nop
+# endif
 
 	/* Initialize caches... */
 	PTR_LA	t9, mips_cache_reset
 	jalr	t9
 	 nop
 
-	/* ... and enable them */
-	li	t0, CONFIG_SYS_MIPS_CACHE_MODE
-	mtc0	t0, CP0_CONFIG
+# ifndef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD
+	/* Initialize any external memory */
+	PTR_LA	t9, lowlevel_init
+	jalr	t9
+	 nop
+# endif
 #endif
 
 	/* Set up temporary stack */
@@ -214,12 +242,9 @@
 	PTR_LI	t0, CONFIG_SYS_MONITOR_BASE
 	PTR_SUB	s1, s2, t0		# s1 <-- relocation offset
 
-	PTR_LA	t3, in_ram
-	PTR_L	t2, -(3 * PTRSIZE)(t3)	# t2 <-- __image_copy_end
+	PTR_LA	t2, __image_copy_end
 	move	t1, a2
 
-	PTR_ADD	gp, s1			# adjust gp
-
 	/*
 	 * t0 = source address
 	 * t1 = target address
@@ -232,32 +257,14 @@
 	blt	t0, t2, 1b
 	 PTR_ADDU t1, PTRSIZE
 
-	/* If caches were enabled, we would have to flush them here. */
-	PTR_SUB	a1, t1, s2		# a1 <-- size
-	PTR_LA	t9, flush_cache
-	jalr	t9
-	 move	a0, s2			# a0 <-- destination address
-
-	/* Jump to where we've relocated ourselves */
-	PTR_ADDIU t0, s2, in_ram - _start
-	jr	t0
-	 nop
-
-	PTR	__rel_dyn_end
-	PTR	__rel_dyn_start
-	PTR	__image_copy_end
-	PTR	_GLOBAL_OFFSET_TABLE_
-	PTR	num_got_entries
-
-in_ram:
 	/*
 	 * Now we want to update GOT.
 	 *
 	 * GOT[0] is reserved. GOT[1] is also reserved for the dynamic object
 	 * generated by GNU ld. Skip these reserved entries from relocation.
 	 */
-	PTR_L	t3, -(1 * PTRSIZE)(t0)	# t3 <-- num_got_entries
-	PTR_L	t8, -(2 * PTRSIZE)(t0)	# t8 <-- _GLOBAL_OFFSET_TABLE_
+	PTR_LA	t3, num_got_entries
+	PTR_LA	t8, _GLOBAL_OFFSET_TABLE_
 	PTR_ADD	t8, s1			# t8 now holds relocated _G_O_T_
 	PTR_ADDIU t8, t8, 2 * PTRSIZE	# skipping first two entries
 	PTR_LI	t2, 2
@@ -272,8 +279,8 @@
 	 PTR_ADDIU t8, PTRSIZE
 
 	/* Update dynamic relocations */
-	PTR_L	t1, -(4 * PTRSIZE)(t0)	# t1 <-- __rel_dyn_start
-	PTR_L	t2, -(5 * PTRSIZE)(t0)	# t2 <-- __rel_dyn_end
+	PTR_LA	t1, __rel_dyn_start
+	PTR_LA	t2, __rel_dyn_end
 
 	b	2f			# skip first reserved entry
 	 PTR_ADDIU t1, 2 * PTRSIZE
@@ -298,6 +305,20 @@
 	 PTR_ADDIU t1, 2 * PTRSIZE	# each rel.dyn entry is 2*PTRSIZE bytes
 
 	/*
+	 * Flush caches to ensure our newly modified instructions are visible
+	 * to the instruction cache. We're still running with the old GOT, so
+	 * apply the reloc offset to the start address.
+	 */
+	PTR_LA	a0, __text_start
+	PTR_LA	a1, __text_end
+	PTR_SUB	a1, a1, a0
+	PTR_LA	t9, flush_cache
+	jalr	t9
+	 PTR_ADD	a0, s1
+
+	PTR_ADD	gp, s1			# adjust gp
+
+	/*
 	 * Clear BSS
 	 *
 	 * GOT is now relocated. Thus __bss_start and __bss_end can be
diff --git a/arch/mips/cpu/u-boot.lds b/arch/mips/cpu/u-boot.lds
index 7d71c11..0129c99 100644
--- a/arch/mips/cpu/u-boot.lds
+++ b/arch/mips/cpu/u-boot.lds
@@ -19,7 +19,9 @@
 
 	. = ALIGN(4);
 	.text : {
+		__text_start = .;
 		*(.text*)
+		__text_end = .;
 	}
 
 	. = ALIGN(4);
diff --git a/arch/mips/dts/Makefile b/arch/mips/dts/Makefile
index 2f04d73..30fcc2b 100644
--- a/arch/mips/dts/Makefile
+++ b/arch/mips/dts/Makefile
@@ -4,8 +4,10 @@
 
 dtb-$(CONFIG_TARGET_AP121) += ap121.dtb
 dtb-$(CONFIG_TARGET_AP143) += ap143.dtb
+dtb-$(CONFIG_TARGET_BOSTON) += img,boston.dtb
 dtb-$(CONFIG_TARGET_MALTA) += mti,malta.dtb
 dtb-$(CONFIG_TARGET_PIC32MZDASK) += pic32mzda_sk.dtb
+dtb-$(CONFIG_TARGET_XILFPGA) += nexys4ddr.dtb
 dtb-$(CONFIG_BOARD_TPLINK_WDR4300) += tplink_wdr4300.dtb
 
 targets += $(dtb-y)
diff --git a/arch/mips/dts/img,boston.dts b/arch/mips/dts/img,boston.dts
new file mode 100644
index 0000000..1d4eeda
--- /dev/null
+++ b/arch/mips/dts/img,boston.dts
@@ -0,0 +1,222 @@
+/dts-v1/;
+
+#include <dt-bindings/clock/boston-clock.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/mips-gic.h>
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	compatible = "img,boston";
+
+	chosen {
+		stdout-path = &uart0;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "img,mips";
+			reg = <0>;
+			clocks = <&clk_boston BOSTON_CLK_CPU>;
+		};
+	};
+
+	memory@0 {
+		device_type = "memory";
+		reg = <0x00000000 0x10000000>;
+	};
+
+	gic: interrupt-controller {
+		compatible = "mti,gic";
+
+		interrupt-controller;
+		#interrupt-cells = <3>;
+
+		timer {
+			compatible = "mti,gic-timer";
+			interrupts = <GIC_LOCAL 1 IRQ_TYPE_NONE>;
+			clocks = <&clk_boston BOSTON_CLK_CPU>;
+		};
+	};
+
+	pci0: pci@10000000 {
+		status = "disabled";
+		compatible = "xlnx,axi-pcie-host-1.00.a";
+		device_type = "pci";
+		reg = <0x10000000 0x2000000>;
+
+		#address-cells = <3>;
+		#size-cells = <2>;
+		#interrupt-cells = <1>;
+
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_SHARED 2 IRQ_TYPE_LEVEL_HIGH>;
+
+		ranges = <0x02000000 0 0x40000000
+			  0x40000000 0 0x40000000>;
+
+		interrupt-map-mask = <0 0 0 7>;
+		interrupt-map = <0 0 0 1 &pci0_intc 0>,
+				<0 0 0 2 &pci0_intc 1>,
+				<0 0 0 3 &pci0_intc 2>,
+				<0 0 0 4 &pci0_intc 3>;
+
+		pci0_intc: interrupt-controller {
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <1>;
+		};
+	};
+
+	pci1: pci@12000000 {
+		status = "disabled";
+		compatible = "xlnx,axi-pcie-host-1.00.a";
+		device_type = "pci";
+		reg = <0x12000000 0x2000000>;
+
+		#address-cells = <3>;
+		#size-cells = <2>;
+		#interrupt-cells = <1>;
+
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_SHARED 1 IRQ_TYPE_LEVEL_HIGH>;
+
+		ranges = <0x02000000 0 0x20000000
+			  0x20000000 0 0x20000000>;
+
+		interrupt-map-mask = <0 0 0 7>;
+		interrupt-map = <0 0 0 1 &pci1_intc 0>,
+				<0 0 0 2 &pci1_intc 1>,
+				<0 0 0 3 &pci1_intc 2>,
+				<0 0 0 4 &pci1_intc 3>;
+
+		pci1_intc: interrupt-controller {
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <1>;
+		};
+	};
+
+	pci2: pci@14000000 {
+		compatible = "xlnx,axi-pcie-host-1.00.a";
+		device_type = "pci";
+		reg = <0x14000000 0x2000000>;
+
+		#address-cells = <3>;
+		#size-cells = <2>;
+		#interrupt-cells = <1>;
+
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_SHARED 0 IRQ_TYPE_LEVEL_HIGH>;
+
+		ranges = <0x02000000 0 0x16000000
+			  0x16000000 0 0x100000>;
+
+		interrupt-map-mask = <0 0 0 7>;
+		interrupt-map = <0 0 0 1 &pci2_intc 0>,
+				<0 0 0 2 &pci2_intc 1>,
+				<0 0 0 3 &pci2_intc 2>,
+				<0 0 0 4 &pci2_intc 3>;
+
+		pci2_intc: interrupt-controller {
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <1>;
+		};
+
+		pci2_root@0,0,0 {
+			compatible = "pci10ee,7021";
+			reg = <0x00000000 0 0 0 0>;
+
+			#address-cells = <3>;
+			#size-cells = <2>;
+			#interrupt-cells = <1>;
+
+			eg20t_bridge@1,0,0 {
+				compatible = "pci8086,8800";
+				reg = <0x00010000 0 0 0 0>;
+
+				#address-cells = <3>;
+				#size-cells = <2>;
+				#interrupt-cells = <1>;
+
+				eg20t_mac@2,0,1 {
+					compatible = "pci8086,8802";
+					reg = <0x00020100 0 0 0 0>;
+					phy-reset-gpios = <&eg20t_gpio 6 GPIO_ACTIVE_LOW>;
+				};
+
+				eg20t_gpio: eg20t_gpio@2,0,2 {
+					compatible = "pci8086,8803";
+					reg = <0x00020200 0 0 0 0>;
+
+					gpio-controller;
+					#gpio-cells = <2>;
+				};
+
+				eg20t_i2c@2,12,2 {
+					compatible = "pci8086,8817";
+					reg = <0x00026200 0 0 0 0>;
+
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					rtc@0x68 {
+						compatible = "st,m41t81s";
+						reg = <0x68>;
+					};
+				};
+			};
+		};
+	};
+
+	plat_regs: system-controller@17ffd000 {
+		compatible = "img,boston-platform-regs", "syscon";
+		reg = <0x17ffd000 0x1000>;
+		u-boot,dm-pre-reloc;
+	};
+
+	clk_boston: clock {
+		compatible = "img,boston-clock";
+		#clock-cells = <1>;
+		regmap = <&plat_regs>;
+		u-boot,dm-pre-reloc;
+	};
+
+	reboot: syscon-reboot {
+		compatible = "syscon-reboot";
+		regmap = <&plat_regs>;
+		offset = <0x10>;
+		mask = <0x10>;
+	};
+
+	uart0: uart@17ffe000 {
+		compatible = "ns16550a";
+		reg = <0x17ffe000 0x1000>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_SHARED 3 IRQ_TYPE_LEVEL_HIGH>;
+
+		clocks = <&clk_boston BOSTON_CLK_SYS>;
+
+		u-boot,dm-pre-reloc;
+	};
+
+	lcd: lcd@17fff000 {
+		compatible = "img,boston-lcd";
+		reg = <0x17fff000 0x8>;
+	};
+
+	flash@18000000 {
+		compatible = "cfi-flash";
+		reg = <0x18000000 0x8000000>;
+		bank-width = <2>;
+	};
+};
diff --git a/arch/mips/dts/microAptiv.dtsi b/arch/mips/dts/microAptiv.dtsi
new file mode 100644
index 0000000..81d518e
--- /dev/null
+++ b/arch/mips/dts/microAptiv.dtsi
@@ -0,0 +1,21 @@
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	compatible = "img,xilfpga";
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "mips,m14Kc";
+			clocks	= <&ext>;
+			reg = <0>;
+		};
+	};
+
+	ext: ext {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+	};
+};
diff --git a/arch/mips/dts/nexys4ddr.dts b/arch/mips/dts/nexys4ddr.dts
new file mode 100644
index 0000000..e254ab1
--- /dev/null
+++ b/arch/mips/dts/nexys4ddr.dts
@@ -0,0 +1,62 @@
+/dts-v1/;
+
+#include "microAptiv.dtsi"
+
+/ {
+	compatible = "digilent,nexys4ddr";
+
+	memory {
+		device_type = "memory";
+		reg = <0x0 0x08000000>;
+	};
+
+	cpuintc: interrupt-controller@0 {
+		#address-cells = <0>;
+		#interrupt-cells = <1>;
+		interrupt-controller;
+		compatible = "mti,cpu-interrupt-controller";
+	};
+
+	aliases {
+		console = &axi_uart16550;
+	};
+
+	axi_ethernetlite: ethernet@10e00000 {
+		compatible = "xlnx,xps-ethernetlite-1.00.a";
+		device_type = "network";
+		local-mac-address = [08 86 4C 0D F7 09];
+		phy-handle = <&phy0>;
+		reg = <0x10e00000 0x10000>;
+		xlnx,duplex = <0x1>;
+		xlnx,include-global-buffers = <0x1>;
+		xlnx,include-internal-loopback = <0x0>;
+		xlnx,include-mdio = <0x1>;
+		xlnx,instance = "axi_ethernetlite_inst";
+		xlnx,rx-ping-pong = <0x1>;
+		xlnx,s-axi-id-width = <0x1>;
+		xlnx,tx-ping-pong = <0x1>;
+		xlnx,use-internal = <0x0>;
+		mdio {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			phy0: phy@1 {
+				compatible = <0x0007c0f0 0xfffffff0>;
+				device_type = "ethernet-phy";
+				reg = <1>;
+			} ;
+		} ;
+        } ;
+
+
+	axi_uart16550: serial@10400000 {
+		compatible = "ns16550a";
+		reg = <0x10400000 0x10000>;
+
+		reg-shift = <2>;
+		reg-offset = <0x1000>;
+
+		clock-frequency = <50000000>;
+
+	};
+};
+
diff --git a/arch/mips/include/asm/cache.h b/arch/mips/include/asm/cache.h
index 0cea581..669c362 100644
--- a/arch/mips/include/asm/cache.h
+++ b/arch/mips/include/asm/cache.h
@@ -19,4 +19,13 @@
  */
 #define CONFIG_SYS_CACHELINE_SIZE ARCH_DMA_MINALIGN
 
+/**
+ * mips_cache_probe() - Probe the properties of the caches
+ *
+ * Call this to probe the properties such as line sizes of the caches
+ * present in the system, if any. This must be done before cache maintenance
+ * functions such as flush_cache may be called.
+ */
+void mips_cache_probe(void);
+
 #endif /* __MIPS_CACHE_H__ */
diff --git a/arch/mips/include/asm/cm.h b/arch/mips/include/asm/cm.h
new file mode 100644
index 0000000..b9ab0c6
--- /dev/null
+++ b/arch/mips/include/asm/cm.h
@@ -0,0 +1,62 @@
+/*
+ * MIPS Coherence Manager (CM) Register Definitions
+ *
+ * Copyright (c) 2016 Imagination Technologies Ltd.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+#ifndef __MIPS_ASM_CM_H__
+#define __MIPS_ASM_CM_H__
+
+/* Global Control Register (GCR) offsets */
+#define GCR_BASE			0x0008
+#define GCR_BASE_UPPER			0x000c
+#define GCR_REV				0x0030
+#define GCR_L2_CONFIG			0x0130
+#define GCR_L2_TAG_ADDR			0x0600
+#define GCR_L2_TAG_ADDR_UPPER		0x0604
+#define GCR_L2_TAG_STATE		0x0608
+#define GCR_L2_TAG_STATE_UPPER		0x060c
+#define GCR_L2_DATA			0x0610
+#define GCR_L2_DATA_UPPER		0x0614
+#define GCR_Cx_COHERENCE		0x2008
+
+/* GCR_REV CM versions */
+#define GCR_REV_CM3			0x0800
+
+/* GCR_L2_CONFIG fields */
+#define GCR_L2_CONFIG_ASSOC_SHIFT	0
+#define GCR_L2_CONFIG_ASSOC_BITS	8
+#define GCR_L2_CONFIG_LINESZ_SHIFT	8
+#define GCR_L2_CONFIG_LINESZ_BITS	4
+#define GCR_L2_CONFIG_SETSZ_SHIFT	12
+#define GCR_L2_CONFIG_SETSZ_BITS	4
+#define GCR_L2_CONFIG_BYPASS		(1 << 20)
+
+/* GCR_Cx_COHERENCE */
+#define GCR_Cx_COHERENCE_DOM_EN		(0xff << 0)
+#define GCR_Cx_COHERENCE_EN		(0x1 << 0)
+
+#ifndef __ASSEMBLY__
+
+#include <asm/io.h>
+
+static inline void *mips_cm_base(void)
+{
+	return (void *)CKSEG1ADDR(CONFIG_MIPS_CM_BASE);
+}
+
+static inline unsigned long mips_cm_l2_line_size(void)
+{
+	unsigned long l2conf, line_sz;
+
+	l2conf = __raw_readl(mips_cm_base() + GCR_L2_CONFIG);
+
+	line_sz = l2conf >> GCR_L2_CONFIG_LINESZ_SHIFT;
+	line_sz &= GENMASK(GCR_L2_CONFIG_LINESZ_BITS - 1, 0);
+	return line_sz ? (2 << line_sz) : 0;
+}
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* __MIPS_ASM_CM_H__ */
diff --git a/arch/mips/include/asm/global_data.h b/arch/mips/include/asm/global_data.h
index 37f8ed5..0078bbe 100644
--- a/arch/mips/include/asm/global_data.h
+++ b/arch/mips/include/asm/global_data.h
@@ -21,6 +21,13 @@
 	unsigned long rev;
 	unsigned long ver;
 #endif
+#ifdef CONFIG_SYS_CACHE_SIZE_AUTO
+	unsigned short l1i_line_size;
+	unsigned short l1d_line_size;
+#endif
+#ifdef CONFIG_MIPS_L2_CACHE
+	unsigned short l2_line_size;
+#endif
 };
 
 #include <asm-generic/global_data.h>
diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h
index 3185dc7..9ab5063 100644
--- a/arch/mips/include/asm/mipsregs.h
+++ b/arch/mips/include/asm/mipsregs.h
@@ -39,6 +39,7 @@
 #define CP0_ENTRYLO0 $2
 #define CP0_ENTRYLO1 $3
 #define CP0_CONF $3
+#define CP0_GLOBALNUMBER $3, 1
 #define CP0_CONTEXT $4
 #define CP0_PAGEMASK $5
 #define CP0_WIRED $6
@@ -361,6 +362,11 @@
 #define CAUSEF_BD		(_ULCAST_(1)   << 31)
 
 /*
+ * Bits in the coprocessor 0 EBase register.
+ */
+#define EBASE_CPUNUM		0x3ff
+
+/*
  * Bits in the coprocessor 0 config register.
  */
 /* Generic bits.  */
@@ -450,6 +456,7 @@
 #define MIPS_CONF_MT_FTLB	(_ULCAST_(4) <<  7)
 #define MIPS_CONF_AR		(_ULCAST_(7) << 10)
 #define MIPS_CONF_AT		(_ULCAST_(3) << 13)
+#define MIPS_CONF_IMPL		(_ULCAST_(0x1ff) << 16)
 #define MIPS_CONF_M		(_ULCAST_(1) << 31)
 
 /*
@@ -484,9 +491,13 @@
 #define MIPS_CONF1_TLBS_SIZE    (6)
 #define MIPS_CONF1_TLBS         (_ULCAST_(63) << MIPS_CONF1_TLBS_SHIFT)
 
+#define MIPS_CONF2_SA_SHF	0
 #define MIPS_CONF2_SA		(_ULCAST_(15) << 0)
+#define MIPS_CONF2_SL_SHF	4
 #define MIPS_CONF2_SL		(_ULCAST_(15) << 4)
+#define MIPS_CONF2_SS_SHF	8
 #define MIPS_CONF2_SS		(_ULCAST_(15) << 8)
+#define MIPS_CONF2_L2B		(_ULCAST_(1) << 12)
 #define MIPS_CONF2_SU		(_ULCAST_(15) << 12)
 #define MIPS_CONF2_TA		(_ULCAST_(15) << 16)
 #define MIPS_CONF2_TL		(_ULCAST_(15) << 20)
@@ -548,8 +559,10 @@
 #define MIPS_CONF5_MRP		(_ULCAST_(1) << 3)
 #define MIPS_CONF5_LLB		(_ULCAST_(1) << 4)
 #define MIPS_CONF5_MVH		(_ULCAST_(1) << 5)
+#define MIPS_CONF5_VP		(_ULCAST_(1) << 7)
 #define MIPS_CONF5_FRE		(_ULCAST_(1) << 8)
 #define MIPS_CONF5_UFE		(_ULCAST_(1) << 9)
+#define MIPS_CONF5_L2C		(_ULCAST_(1) << 10)
 #define MIPS_CONF5_MSAEN	(_ULCAST_(1) << 27)
 #define MIPS_CONF5_EVA		(_ULCAST_(1) << 28)
 #define MIPS_CONF5_CV		(_ULCAST_(1) << 29)
diff --git a/arch/mips/lib/cache.c b/arch/mips/lib/cache.c
index db81953..bd14ba6 100644
--- a/arch/mips/lib/cache.c
+++ b/arch/mips/lib/cache.c
@@ -7,34 +7,85 @@
 
 #include <common.h>
 #include <asm/cacheops.h>
+#include <asm/cm.h>
 #include <asm/mipsregs.h>
 
-static inline unsigned long icache_line_size(void)
+DECLARE_GLOBAL_DATA_PTR;
+
+static void probe_l2(void)
 {
-	unsigned long conf1, il;
+#ifdef CONFIG_MIPS_L2_CACHE
+	unsigned long conf2, sl;
+	bool l2c = false;
 
-	if (!config_enabled(CONFIG_SYS_CACHE_SIZE_AUTO))
-		return CONFIG_SYS_ICACHE_LINE_SIZE;
+	if (!(read_c0_config1() & MIPS_CONF_M))
+		return;
+
+	conf2 = read_c0_config2();
+
+	if (__mips_isa_rev >= 6) {
+		l2c = conf2 & MIPS_CONF_M;
+		if (l2c)
+			l2c = read_c0_config3() & MIPS_CONF_M;
+		if (l2c)
+			l2c = read_c0_config4() & MIPS_CONF_M;
+		if (l2c)
+			l2c = read_c0_config5() & MIPS_CONF5_L2C;
+	}
+
+	if (l2c && config_enabled(CONFIG_MIPS_CM)) {
+		gd->arch.l2_line_size = mips_cm_l2_line_size();
+	} else if (l2c) {
+		/* We don't know how to retrieve L2 config on this system */
+		BUG();
+	} else {
+		sl = (conf2 & MIPS_CONF2_SL) >> MIPS_CONF2_SL_SHF;
+		gd->arch.l2_line_size = sl ? (2 << sl) : 0;
+	}
+#endif
+}
+
+void mips_cache_probe(void)
+{
+#ifdef CONFIG_SYS_CACHE_SIZE_AUTO
+	unsigned long conf1, il, dl;
 
 	conf1 = read_c0_config1();
+
 	il = (conf1 & MIPS_CONF1_IL) >> MIPS_CONF1_IL_SHF;
-	if (!il)
-		return 0;
-	return 2 << il;
+	dl = (conf1 & MIPS_CONF1_DL) >> MIPS_CONF1_DL_SHF;
+
+	gd->arch.l1i_line_size = il ? (2 << il) : 0;
+	gd->arch.l1d_line_size = dl ? (2 << dl) : 0;
+#endif
+	probe_l2();
 }
 
-static inline unsigned long dcache_line_size(void)
+static inline unsigned long icache_line_size(void)
 {
-	unsigned long conf1, dl;
+#ifdef CONFIG_SYS_CACHE_SIZE_AUTO
+	return gd->arch.l1i_line_size;
+#else
+	return CONFIG_SYS_ICACHE_LINE_SIZE;
+#endif
+}
 
-	if (!config_enabled(CONFIG_SYS_CACHE_SIZE_AUTO))
-		return CONFIG_SYS_DCACHE_LINE_SIZE;
+static inline unsigned long dcache_line_size(void)
+{
+#ifdef CONFIG_SYS_CACHE_SIZE_AUTO
+	return gd->arch.l1d_line_size;
+#else
+	return CONFIG_SYS_DCACHE_LINE_SIZE;
+#endif
+}
 
-	conf1 = read_c0_config1();
-	dl = (conf1 & MIPS_CONF1_DL) >> MIPS_CONF1_DL_SHF;
-	if (!dl)
-		return 0;
-	return 2 << dl;
+static inline unsigned long scache_line_size(void)
+{
+#ifdef CONFIG_MIPS_L2_CACHE
+	return gd->arch.l2_line_size;
+#else
+	return 0;
+#endif
 }
 
 #define cache_loop(start, end, lsize, ops...) do {			\
@@ -53,12 +104,13 @@
 {
 	unsigned long ilsize = icache_line_size();
 	unsigned long dlsize = dcache_line_size();
+	unsigned long slsize = scache_line_size();
 
 	/* aend will be miscalculated when size is zero, so we return here */
 	if (size == 0)
 		return;
 
-	if (ilsize == dlsize) {
+	if ((ilsize == dlsize) && !slsize) {
 		/* flush I-cache & D-cache simultaneously */
 		cache_loop(start_addr, start_addr + size, ilsize,
 			   HIT_WRITEBACK_INV_D, HIT_INVALIDATE_I);
@@ -68,6 +120,11 @@
 	/* flush D-cache */
 	cache_loop(start_addr, start_addr + size, dlsize, HIT_WRITEBACK_INV_D);
 
+	/* flush L2 cache */
+	if (slsize)
+		cache_loop(start_addr, start_addr + size, slsize,
+			   HIT_WRITEBACK_INV_SD);
+
 	/* flush I-cache */
 	cache_loop(start_addr, start_addr + size, ilsize, HIT_INVALIDATE_I);
 }
@@ -75,21 +132,31 @@
 void flush_dcache_range(ulong start_addr, ulong stop)
 {
 	unsigned long lsize = dcache_line_size();
+	unsigned long slsize = scache_line_size();
 
 	/* aend will be miscalculated when size is zero, so we return here */
 	if (start_addr == stop)
 		return;
 
 	cache_loop(start_addr, stop, lsize, HIT_WRITEBACK_INV_D);
+
+	/* flush L2 cache */
+	if (slsize)
+		cache_loop(start_addr, stop, slsize, HIT_WRITEBACK_INV_SD);
 }
 
 void invalidate_dcache_range(ulong start_addr, ulong stop)
 {
 	unsigned long lsize = dcache_line_size();
+	unsigned long slsize = scache_line_size();
 
 	/* aend will be miscalculated when size is zero, so we return here */
 	if (start_addr == stop)
 		return;
 
+	/* invalidate L2 cache */
+	if (slsize)
+		cache_loop(start_addr, stop, slsize, HIT_INVALIDATE_SD);
+
 	cache_loop(start_addr, stop, lsize, HIT_INVALIDATE_D);
 }
diff --git a/arch/mips/lib/cache_init.S b/arch/mips/lib/cache_init.S
index bc8ab27..698a5af 100644
--- a/arch/mips/lib/cache_init.S
+++ b/arch/mips/lib/cache_init.S
@@ -13,6 +13,7 @@
 #include <asm/mipsregs.h>
 #include <asm/addrspace.h>
 #include <asm/cacheops.h>
+#include <asm/cm.h>
 
 #ifndef CONFIG_SYS_MIPS_CACHE_MODE
 #define CONFIG_SYS_MIPS_CACHE_MODE CONF_CM_CACHABLE_NONCOHERENT
@@ -95,22 +96,147 @@
  * with good parity is available. This routine will initialise an area of
  * memory starting at location zero to be used as a source of parity.
  *
+ * Note that this function does not follow the standard calling convention &
+ * may clobber typically callee-saved registers.
+ *
  * RETURNS: N/A
  *
  */
+#define R_RETURN	s0
+#define R_IC_SIZE	s1
+#define R_IC_LINE	s2
+#define R_DC_SIZE	s3
+#define R_DC_LINE	s4
+#define R_L2_SIZE	s5
+#define R_L2_LINE	s6
+#define R_L2_BYPASSED	s7
+#define R_L2_L2C	t8
 LEAF(mips_cache_reset)
+	move	R_RETURN, ra
+
+#ifdef CONFIG_MIPS_L2_CACHE
+	/*
+	 * For there to be an L2 present, Config2 must be present. If it isn't
+	 * then we proceed knowing there's no L2 cache.
+	 */
+	move	R_L2_SIZE, zero
+	move	R_L2_LINE, zero
+	move	R_L2_BYPASSED, zero
+	move	R_L2_L2C, zero
+	mfc0	t0, CP0_CONFIG, 1
+	bgez	t0, l2_probe_done
+
+	/*
+	 * From MIPSr6 onwards the L2 cache configuration might not be reported
+	 * by Config2. The Config5.L2C bit indicates whether this is the case,
+	 * and if it is then we need knowledge of where else to look. For cores
+	 * from Imagination Technologies this is a CM GCR.
+	 */
+# if __mips_isa_rev >= 6
+	/* Check that Config5 exists */
+	mfc0	t0, CP0_CONFIG, 2
+	bgez	t0, l2_probe_cop0
+	mfc0	t0, CP0_CONFIG, 3
+	bgez	t0, l2_probe_cop0
+	mfc0	t0, CP0_CONFIG, 4
+	bgez	t0, l2_probe_cop0
+
+	/* Check Config5.L2C is set */
+	mfc0	t0, CP0_CONFIG, 5
+	and	R_L2_L2C, t0, MIPS_CONF5_L2C
+	beqz	R_L2_L2C, l2_probe_cop0
+
+	/* Config5.L2C is set */
+#  ifdef CONFIG_MIPS_CM
+	/* The CM will provide L2 configuration */
+	PTR_LI	t0, CKSEG1ADDR(CONFIG_MIPS_CM_BASE)
+	lw	t1, GCR_L2_CONFIG(t0)
+	bgez	t1, l2_probe_done
+
+	ext	R_L2_LINE, t1, \
+		GCR_L2_CONFIG_LINESZ_SHIFT, GCR_L2_CONFIG_LINESZ_BITS
+	beqz	R_L2_LINE, l2_probe_done
+	li	t2, 2
+	sllv	R_L2_LINE, t2, R_L2_LINE
+
+	ext	t2, t1, GCR_L2_CONFIG_ASSOC_SHIFT, GCR_L2_CONFIG_ASSOC_BITS
+	addiu	t2, t2, 1
+	mul	R_L2_SIZE, R_L2_LINE, t2
+
+	ext	t2, t1, GCR_L2_CONFIG_SETSZ_SHIFT, GCR_L2_CONFIG_SETSZ_BITS
+	sllv	R_L2_SIZE, R_L2_SIZE, t2
+	li	t2, 64
+	mul	R_L2_SIZE, R_L2_SIZE, t2
+
+	/* Bypass the L2 cache so that we can init the L1s early */
+	or	t1, t1, GCR_L2_CONFIG_BYPASS
+	sw	t1, GCR_L2_CONFIG(t0)
+	sync
+	li	R_L2_BYPASSED, 1
+
+	/* Zero the L2 tag registers */
+	sw	zero, GCR_L2_TAG_ADDR(t0)
+	sw	zero, GCR_L2_TAG_ADDR_UPPER(t0)
+	sw	zero, GCR_L2_TAG_STATE(t0)
+	sw	zero, GCR_L2_TAG_STATE_UPPER(t0)
+	sw	zero, GCR_L2_DATA(t0)
+	sw	zero, GCR_L2_DATA_UPPER(t0)
+	sync
+#  else
+	/* We don't know how to retrieve L2 configuration on this system */
+#  endif
+	b	l2_probe_done
+# endif
+
+	/*
+	 * For pre-r6 systems, or r6 systems with Config5.L2C==0, probe the L2
+	 * cache configuration from the cop0 Config2 register.
+	 */
+l2_probe_cop0:
+	mfc0	t0, CP0_CONFIG, 2
+
+	srl	R_L2_LINE, t0, MIPS_CONF2_SL_SHF
+	andi	R_L2_LINE, R_L2_LINE, MIPS_CONF2_SL >> MIPS_CONF2_SL_SHF
+	beqz	R_L2_LINE, l2_probe_done
+	li	t1, 2
+	sllv	R_L2_LINE, t1, R_L2_LINE
+
+	srl	t1, t0, MIPS_CONF2_SA_SHF
+	andi	t1, t1, MIPS_CONF2_SA >> MIPS_CONF2_SA_SHF
+	addiu	t1, t1, 1
+	mul	R_L2_SIZE, R_L2_LINE, t1
+
+	srl	t1, t0, MIPS_CONF2_SS_SHF
+	andi	t1, t1, MIPS_CONF2_SS >> MIPS_CONF2_SS_SHF
+	sllv	R_L2_SIZE, R_L2_SIZE, t1
+	li	t1, 64
+	mul	R_L2_SIZE, R_L2_SIZE, t1
+
+	/* Attempt to bypass the L2 so that we can init the L1s early */
+	or	t0, t0, MIPS_CONF2_L2B
+	mtc0	t0, CP0_CONFIG, 2
+	ehb
+	mfc0	t0, CP0_CONFIG, 2
+	and	R_L2_BYPASSED, t0, MIPS_CONF2_L2B
+
+	/* Zero the L2 tag registers */
+	mtc0	zero, CP0_TAGLO, 4
+	ehb
+l2_probe_done:
+#endif
+
 #ifndef CONFIG_SYS_CACHE_SIZE_AUTO
-	li	t2, CONFIG_SYS_ICACHE_SIZE
-	li	t8, CONFIG_SYS_ICACHE_LINE_SIZE
+	li	R_IC_SIZE, CONFIG_SYS_ICACHE_SIZE
+	li	R_IC_LINE, CONFIG_SYS_ICACHE_LINE_SIZE
 #else
-	l1_info	t2, t8, MIPS_CONF1_IA_SHF
+	l1_info	R_IC_SIZE, R_IC_LINE, MIPS_CONF1_IA_SHF
 #endif
 
 #ifndef CONFIG_SYS_CACHE_SIZE_AUTO
-	li	t3, CONFIG_SYS_DCACHE_SIZE
-	li	t9, CONFIG_SYS_DCACHE_LINE_SIZE
+	li	R_DC_SIZE, CONFIG_SYS_DCACHE_SIZE
+	li	R_DC_LINE, CONFIG_SYS_DCACHE_LINE_SIZE
 #else
-	l1_info	t3, t9, MIPS_CONF1_DA_SHF
+	l1_info	R_DC_SIZE, R_DC_LINE, MIPS_CONF1_DA_SHF
 #endif
 
 #ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD
@@ -123,9 +249,9 @@
 	li	v0, CONFIG_SYS_DCACHE_SIZE
 #endif
 #else
-	move	v0, t2
-	sltu	t1, t2, t3
-	movn	v0, t3, t1
+	move	v0, R_IC_SIZE
+	sltu	t1, R_IC_SIZE, R_DC_SIZE
+	movn	v0, R_DC_SIZE, t1
 #endif
 	/*
 	 * Now clear that much memory starting from zero.
@@ -138,13 +264,36 @@
 
 #endif /* CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD */
 
+#ifdef CONFIG_MIPS_L2_CACHE
+	/*
+	 * If the L2 is bypassed, init the L1 first so that we can execute the
+	 * rest of the cache initialisation using the L1 instruction cache.
+	 */
+	bnez		R_L2_BYPASSED, l1_init
+
+l2_init:
+	PTR_LI		t0, INDEX_BASE
+	PTR_ADDU	t1, t0, R_L2_SIZE
+1:	cache		INDEX_STORE_TAG_SD, 0(t0)
+	PTR_ADDU	t0, t0, R_L2_LINE
+	bne		t0, t1, 1b
+
+	/*
+	 * If the L2 was bypassed then we already initialised the L1s before
+	 * the L2, so we are now done.
+	 */
+	bnez		R_L2_BYPASSED, l2_unbypass
+#endif
+
 	/*
 	 * The TagLo registers used depend upon the CPU implementation, but the
 	 * architecture requires that it is safe for software to write to both
 	 * TagLo selects 0 & 2 covering supported cases.
 	 */
+l1_init:
 	mtc0		zero, CP0_TAGLO
 	mtc0		zero, CP0_TAGLO, 2
+	ehb
 
 	/*
 	 * The caches are probably in an indeterminate state, so we force good
@@ -158,40 +307,122 @@
 	/*
 	 * Initialize the I-cache first,
 	 */
-	blez		t2, 1f
+	blez		R_IC_SIZE, 1f
 	PTR_LI		t0, INDEX_BASE
-	PTR_ADDU	t1, t0, t2
+	PTR_ADDU	t1, t0, R_IC_SIZE
 	/* clear tag to invalidate */
-	cache_loop	t0, t1, t8, INDEX_STORE_TAG_I
+	cache_loop	t0, t1, R_IC_LINE, INDEX_STORE_TAG_I
 #ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD
 	/* fill once, so data field parity is correct */
 	PTR_LI		t0, INDEX_BASE
-	cache_loop	t0, t1, t8, FILL
+	cache_loop	t0, t1, R_IC_LINE, FILL
 	/* invalidate again - prudent but not strictly neccessary */
 	PTR_LI		t0, INDEX_BASE
-	cache_loop	t0, t1, t8, INDEX_STORE_TAG_I
+	cache_loop	t0, t1, R_IC_LINE, INDEX_STORE_TAG_I
+#endif
+
+	/* Enable use of the I-cache by setting Config.K0 */
+	sync
+	mfc0		t0, CP0_CONFIG
+	li		t1, CONFIG_SYS_MIPS_CACHE_MODE
+#if __mips_isa_rev >= 2
+	ins		t0, t1, 0, 3
+#else
+	ori		t0, t0, CONF_CM_CMASK
+	xori		t0, t0, CONF_CM_CMASK
+	or		t0, t0, t1
 #endif
+	mtc0		t0, CP0_CONFIG
 
 	/*
 	 * then initialize D-cache.
 	 */
-1:	blez		t3, 3f
+1:	blez		R_DC_SIZE, 3f
 	PTR_LI		t0, INDEX_BASE
-	PTR_ADDU	t1, t0, t3
+	PTR_ADDU	t1, t0, R_DC_SIZE
 	/* clear all tags */
-	cache_loop	t0, t1, t9, INDEX_STORE_TAG_D
+	cache_loop	t0, t1, R_DC_LINE, INDEX_STORE_TAG_D
 #ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD
 	/* load from each line (in cached space) */
 	PTR_LI		t0, INDEX_BASE
 2:	LONG_L		zero, 0(t0)
-	PTR_ADDU	t0, t9
+	PTR_ADDU	t0, R_DC_LINE
 	bne		t0, t1, 2b
 	/* clear all tags */
 	PTR_LI		t0, INDEX_BASE
-	cache_loop	t0, t1, t9, INDEX_STORE_TAG_D
+	cache_loop	t0, t1, R_DC_LINE, INDEX_STORE_TAG_D
+#endif
+3:
+
+#ifdef CONFIG_MIPS_L2_CACHE
+	/* If the L2 isn't bypassed then we're done */
+	beqz		R_L2_BYPASSED, return
+
+	/* The L2 is bypassed - go initialise it */
+	b		l2_init
+
+l2_unbypass:
+# if __mips_isa_rev >= 6
+	beqz		R_L2_L2C, 1f
+
+	li		t0, CKSEG1ADDR(CONFIG_MIPS_CM_BASE)
+	lw		t1, GCR_L2_CONFIG(t0)
+	xor		t1, t1, GCR_L2_CONFIG_BYPASS
+	sw		t1, GCR_L2_CONFIG(t0)
+	sync
+	ehb
+	b		2f
+# endif
+1:	mfc0		t0, CP0_CONFIG, 2
+	xor		t0, t0, MIPS_CONF2_L2B
+	mtc0		t0, CP0_CONFIG, 2
+	ehb
+
+2:
+# ifdef CONFIG_MIPS_CM
+	/* Config3 must exist for a CM to be present */
+	mfc0		t0, CP0_CONFIG, 1
+	bgez		t0, 2f
+	mfc0		t0, CP0_CONFIG, 2
+	bgez		t0, 2f
+
+	/* Check Config3.CMGCR to determine CM presence */
+	mfc0		t0, CP0_CONFIG, 3
+	and		t0, t0, MIPS_CONF3_CMGCR
+	beqz		t0, 2f
+
+	/* Change Config.K0 to a coherent CCA */
+	mfc0		t0, CP0_CONFIG
+	li		t1, CONF_CM_CACHABLE_COW
+#if __mips_isa_rev >= 2
+	ins		t0, t1, 0, 3
+#else
+	ori		t0, t0, CONF_CM_CMASK
+	xori		t0, t0, CONF_CM_CMASK
+	or		t0, t0, t1
+#endif
+	mtc0		t0, CP0_CONFIG
+
+	/*
+	 * Join the coherent domain such that the caches of this core are kept
+	 * coherent with those of other cores.
+	 */
+	PTR_LI		t0, CKSEG1ADDR(CONFIG_MIPS_CM_BASE)
+	lw		t1, GCR_REV(t0)
+	li		t2, GCR_REV_CM3
+	li		t3, GCR_Cx_COHERENCE_EN
+	bge		t1, t2, 1f
+	li		t3, GCR_Cx_COHERENCE_DOM_EN
+1:	sw		t3, GCR_Cx_COHERENCE(t0)
+	ehb
+2:
+# endif
 #endif
 
-3:	jr	ra
+return:
+	/* Ensure all cache operations complete before returning */
+	sync
+	jr	ra
 	END(mips_cache_reset)
 
 /*
diff --git a/arch/mips/mach-ath79/cpu.c b/arch/mips/mach-ath79/cpu.c
index 5756a06..4ef5092 100644
--- a/arch/mips/mach-ath79/cpu.c
+++ b/arch/mips/mach-ath79/cpu.c
@@ -46,7 +46,7 @@
 	{ATH79_SOC_QCA9561,     "9561", REV_ID_MAJOR_QCA9561,   0},
 };
 
-int arch_cpu_init(void)
+int mach_cpu_init(void)
 {
 	void __iomem *base;
 	enum ath79_soc_type soc = ATH79_SOC_UNKNOWN;
diff --git a/board/imgtec/boston/Kconfig b/board/imgtec/boston/Kconfig
new file mode 100644
index 0000000..ab76a3c
--- /dev/null
+++ b/board/imgtec/boston/Kconfig
@@ -0,0 +1,16 @@
+if TARGET_BOSTON
+
+config SYS_BOARD
+	default "boston"
+
+config SYS_VENDOR
+	default "imgtec"
+
+config SYS_CONFIG_NAME
+	default "boston"
+
+config SYS_TEXT_BASE
+	default 0x9fc00000 if 32BIT
+	default 0xffffffff9fc00000 if 64BIT
+
+endif
diff --git a/board/imgtec/boston/MAINTAINERS b/board/imgtec/boston/MAINTAINERS
new file mode 100644
index 0000000..30dd481
--- /dev/null
+++ b/board/imgtec/boston/MAINTAINERS
@@ -0,0 +1,6 @@
+BOSTON BOARD
+M:	Paul Burton <paul.burton@imgtec.com>
+S:	Maintained
+F:	board/imgtec/boston/
+F:	include/configs/boston.h
+F:	configs/boston_defconfig
diff --git a/board/imgtec/boston/Makefile b/board/imgtec/boston/Makefile
new file mode 100644
index 0000000..deda457
--- /dev/null
+++ b/board/imgtec/boston/Makefile
@@ -0,0 +1,9 @@
+#
+# Copyright (C) 2016 Imagination Technologies
+#
+# SPDX-License-Identifier:	GPL-2.0
+#
+
+obj-y += checkboard.o
+obj-y += ddr.o
+obj-y += lowlevel_init.o
diff --git a/board/imgtec/boston/boston-lcd.h b/board/imgtec/boston/boston-lcd.h
new file mode 100644
index 0000000..9f5c1b9
--- /dev/null
+++ b/board/imgtec/boston/boston-lcd.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2016 Imagination Technologies
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef __BOARD_BOSTON_LCD_H__
+#define __BOARD_BOSTON_LCD_H__
+
+/**
+ * lowlevel_display() - Display a message on Boston's LCD
+ * @msg: The string to display
+ *
+ * Display the string @msg on the 7 character LCD display of the Boston board.
+ * This is typically used for debug or to present some form of status
+ * indication to the user, allowing faults to be identified when things go
+ * wrong early enough that the UART isn't up.
+ */
+void lowlevel_display(const char msg[static 8]);
+
+#endif /* __BOARD_BOSTON_LCD_H__ */
diff --git a/board/imgtec/boston/boston-regs.h b/board/imgtec/boston/boston-regs.h
new file mode 100644
index 0000000..b9dfbb4
--- /dev/null
+++ b/board/imgtec/boston/boston-regs.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2016 Imagination Technologies
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef __BOARD_BOSTON_REGS_H__
+#define __BOARD_BOSTON_REGS_H__
+
+#include <asm/addrspace.h>
+
+#define BOSTON_PLAT_BASE		CKSEG1ADDR(0x17ffd000)
+#define BOSTON_LCD_BASE			CKSEG1ADDR(0x17fff000)
+
+/*
+ * Platform Register Definitions
+ */
+#define BOSTON_PLAT_CORE_CL		(BOSTON_PLAT_BASE + 0x04)
+
+#define BOSTON_PLAT_DDR3STAT		(BOSTON_PLAT_BASE + 0x14)
+# define BOSTON_PLAT_DDR3STAT_CALIB	(1 << 2)
+
+#define BOSTON_PLAT_DDRCONF0		(BOSTON_PLAT_BASE + 0x38)
+# define BOSTON_PLAT_DDRCONF0_SIZE	(0xf << 0)
+
+#endif /* __BOARD_BOSTON_REGS_H__ */
diff --git a/board/imgtec/boston/checkboard.c b/board/imgtec/boston/checkboard.c
new file mode 100644
index 0000000..93eae7f
--- /dev/null
+++ b/board/imgtec/boston/checkboard.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2016 Imagination Technologies
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+
+#include <asm/io.h>
+#include <asm/mipsregs.h>
+
+#include "boston-lcd.h"
+#include "boston-regs.h"
+
+int checkboard(void)
+{
+	u32 changelist;
+
+	lowlevel_display("U-boot  ");
+
+	printf("Board: MIPS Boston\n");
+
+	printf("CPU:   0x%08x", read_c0_prid());
+	changelist = __raw_readl((uint32_t *)BOSTON_PLAT_CORE_CL);
+	if (changelist > 1)
+		printf(" cl%x", changelist);
+	putc('\n');
+
+	return 0;
+}
diff --git a/board/imgtec/boston/ddr.c b/board/imgtec/boston/ddr.c
new file mode 100644
index 0000000..ceffef6
--- /dev/null
+++ b/board/imgtec/boston/ddr.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2016 Imagination Technologies
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+
+#include <asm/io.h>
+
+#include "boston-regs.h"
+
+phys_size_t initdram(int board_type)
+{
+	u32 ddrconf0 = __raw_readl((uint32_t *)BOSTON_PLAT_DDRCONF0);
+
+	return (phys_size_t)(ddrconf0 & BOSTON_PLAT_DDRCONF0_SIZE) << 30;
+}
+
+ulong board_get_usable_ram_top(ulong total_size)
+{
+	DECLARE_GLOBAL_DATA_PTR;
+
+	if (gd->ram_top < CONFIG_SYS_SDRAM_BASE) {
+		/* 2GB wrapped around to 0 */
+		return CKSEG0ADDR(256 << 20);
+	}
+
+	return min_t(unsigned long, gd->ram_top, CKSEG0ADDR(256 << 20));
+}
diff --git a/board/imgtec/boston/lowlevel_init.S b/board/imgtec/boston/lowlevel_init.S
new file mode 100644
index 0000000..0c01aa9
--- /dev/null
+++ b/board/imgtec/boston/lowlevel_init.S
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2016 Imagination Technologies
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <config.h>
+
+#include <asm/addrspace.h>
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+
+#include "boston-regs.h"
+
+.data
+
+msg_ddr_cal:	.ascii "DDR Cal "
+msg_ddr_ok:	.ascii "DDR OK  "
+
+.text
+
+LEAF(lowlevel_init)
+	move	s0, ra
+
+	PTR_LA	a0, msg_ddr_cal
+	bal	lowlevel_display
+
+	PTR_LI	t0, BOSTON_PLAT_DDR3STAT
+1:	lw	t1, 0(t0)
+	andi	t1, t1, BOSTON_PLAT_DDR3STAT_CALIB
+	beqz	t1, 1b
+
+	PTR_LA	a0, msg_ddr_ok
+	bal	lowlevel_display
+
+	move	v0, zero
+	jr	s0
+	END(lowlevel_init)
+
+LEAF(lowlevel_display)
+	.set	push
+	.set	noat
+	PTR_LI	AT, BOSTON_LCD_BASE
+#ifdef CONFIG_64BIT
+	ld	k1, 0(a0)
+	sd	k1, 0(AT)
+#else
+	lw	k1, 0(a0)
+	sw	k1, 0(AT)
+	lw	k1, 4(a0)
+	sw	k1, 4(AT)
+#endif
+	.set	pop
+1:	jr	ra
+	END(lowlevel_display)
diff --git a/board/imgtec/malta/lowlevel_init.S b/board/imgtec/malta/lowlevel_init.S
index 3d48cdc..6df4d9f 100644
--- a/board/imgtec/malta/lowlevel_init.S
+++ b/board/imgtec/malta/lowlevel_init.S
@@ -28,12 +28,6 @@
 
 	.globl	lowlevel_init
 lowlevel_init:
-	/* disable any L2 cache for now */
-	sync
-	mfc0	t0, CP0_CONFIG, 2
-	ori	t0, t0, 0x1 << 12
-	mtc0	t0, CP0_CONFIG, 2
-
 	/* detect the core card */
 	PTR_LI	t0, CKSEG1ADDR(MALTA_REVISION)
 	lw	t0, 0(t0)
diff --git a/board/imgtec/xilfpga/Kconfig b/board/imgtec/xilfpga/Kconfig
new file mode 100644
index 0000000..b078278
--- /dev/null
+++ b/board/imgtec/xilfpga/Kconfig
@@ -0,0 +1,15 @@
+if TARGET_XILFPGA
+
+config SYS_BOARD
+	default "xilfpga"
+
+config SYS_VENDOR
+	default "imgtec"
+
+config SYS_CONFIG_NAME
+	default "imgtec_xilfpga"
+
+config SYS_TEXT_BASE
+	default 0x80C00000
+
+endif
diff --git a/board/imgtec/xilfpga/MAINTAINERS b/board/imgtec/xilfpga/MAINTAINERS
new file mode 100644
index 0000000..aa04532
--- /dev/null
+++ b/board/imgtec/xilfpga/MAINTAINERS
@@ -0,0 +1,6 @@
+XILFPGA BOARD
+M:	Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com>
+S:	Maintained
+F:	board/imgtec/xilfpga
+F:	include/configs/xilfpga.h
+F:	configs/imgtec_xilfpga_defconfig
diff --git a/board/imgtec/xilfpga/Makefile b/board/imgtec/xilfpga/Makefile
new file mode 100644
index 0000000..9aaf9ce
--- /dev/null
+++ b/board/imgtec/xilfpga/Makefile
@@ -0,0 +1,7 @@
+#
+# Copyright (C) 2016, Imagination Technologies Ltd.
+# Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com>
+#
+# SPDX-License-Identifier:      GPL-2.0+
+#
+obj-y := xilfpga.o
diff --git a/board/imgtec/xilfpga/README b/board/imgtec/xilfpga/README
new file mode 100644
index 0000000..ac19d48
--- /dev/null
+++ b/board/imgtec/xilfpga/README
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2016, Imagination Technologies Ltd.
+ *
+ * Zubair Lutfullah Kakakhel, Zubair.Kakakhel@imgtec.com
+ */
+
+MIPSfpga
+=======================================
+
+MIPSfpga is an FPGA based development platform by Imagination Technologies
+As we are dealing with a MIPS core instantiated on an FPGA, specifications
+are fluid and can be varied in RTL.
+
+The example project provided by IMGTEC runs on the Nexys4DDR board by
+Digilent powered by the ARTIX-7 FPGA by Xilinx. Relevant details about
+the example project and the Nexys4DDR board:
+
+- microAptiv UP core m14Kc
+- 50MHz clock speed
+- 128Mbyte DDR RAM	at 0x0000_0000
+- 8Kbyte RAM		at 0x1000_0000
+- axi_intc		at 0x1020_0000
+- axi_uart16550		at 0x1040_0000
+- axi_gpio		at 0x1060_0000
+- axi_i2c		at 0x10A0_0000
+- custom_gpio		at 0x10C0_0000
+- axi_ethernetlite	at 0x10E0_0000
+- 8Kbyte BootRAM	at 0x1FC0_0000
+- 16Mbyte QPI		at 0x1D00_0000
+
+Boot protocol:
+--------------
+
+The BootRAM is a writeable "RAM" in FPGA at 0x1FC0_0000.
+This is for easy reprogrammibility via JTAG.
+
+DDR initialization is already handled by a HW IP block.
+
+When the example project bitstream is loaded, the cpu_reset button
+needs to be pressed.
+
+The bootram initializes the cache and axi_uart
+Then checks if there is anything non 0xffff_ffff at location 0x1D40_0000
+
+If there is, then that is considered as u-boot. u-boot is copied from
+0x1D40_0000 to memory and the bootram jumps into u-boot code.
+
+At this point, the board is ready to load the Linux kernel + buildroot initramfs
+
+This can be done in multiple ways:
+
+1- JTAG load the binary and jump into it.
+2- Load kernel stored in the QSPI flash at 0x1D80_0000
+3- Load uImage via tftp. Ethernet works in u-boot.
+   e.g. env set server ip 192.168.154.45; dhcp uImage; bootm
diff --git a/board/imgtec/xilfpga/xilfpga.c b/board/imgtec/xilfpga/xilfpga.c
new file mode 100644
index 0000000..77a1952
--- /dev/null
+++ b/board/imgtec/xilfpga/xilfpga.c
@@ -0,0 +1,20 @@
+/*
+ * Imagination Technologies MIPSfpga platform code
+ *
+ * Copyright (C) 2016, Imagination Technologies Ltd.
+ *
+ * Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ *
+ */
+
+#include <common.h>
+
+/* initialize the DDR Controller and PHY */
+phys_size_t initdram(int board_type)
+{
+	/* MIG IP block is smart and doesn't need SW
+	 * to do any init */
+	return CONFIG_SYS_SDRAM_SIZE;	/* in bytes */
+}
diff --git a/board/xilinx/zynqmp/zynqmp.c b/board/xilinx/zynqmp/zynqmp.c
index 0c5d997..566b5e8 100644
--- a/board/xilinx/zynqmp/zynqmp.c
+++ b/board/xilinx/zynqmp/zynqmp.c
@@ -16,14 +16,114 @@
 #include <asm/io.h>
 #include <usb.h>
 #include <dwc3-uboot.h>
+#include <zynqmppl.h>
 #include <i2c.h>
+#include <g_dnl.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
+#if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) && \
+    !defined(CONFIG_SPL_BUILD)
+static xilinx_desc zynqmppl = XILINX_ZYNQMP_DESC;
+
+static const struct {
+	uint32_t id;
+	char *name;
+} zynqmp_devices[] = {
+	{
+		.id = 0x10,
+		.name = "3eg",
+	},
+	{
+		.id = 0x11,
+		.name = "2eg",
+	},
+	{
+		.id = 0x20,
+		.name = "5ev",
+	},
+	{
+		.id = 0x21,
+		.name = "4ev",
+	},
+	{
+		.id = 0x30,
+		.name = "7ev",
+	},
+	{
+		.id = 0x38,
+		.name = "9eg",
+	},
+	{
+		.id = 0x39,
+		.name = "6eg",
+	},
+	{
+		.id = 0x40,
+		.name = "11eg",
+	},
+	{
+		.id = 0x50,
+		.name = "15eg",
+	},
+	{
+		.id = 0x58,
+		.name = "19eg",
+	},
+	{
+		.id = 0x59,
+		.name = "17eg",
+	},
+};
+
+static int chip_id(void)
+{
+	struct pt_regs regs;
+	regs.regs[0] = ZYNQMP_SIP_SVC_CSU_DMA_CHIPID;
+	regs.regs[1] = 0;
+	regs.regs[2] = 0;
+	regs.regs[3] = 0;
+
+	smc_call(&regs);
+
+	return regs.regs[0];
+}
+
+static char *zynqmp_get_silicon_idcode_name(void)
+{
+	uint32_t i, id;
+
+	id = chip_id();
+	for (i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) {
+		if (zynqmp_devices[i].id == id)
+			return zynqmp_devices[i].name;
+	}
+	return "unknown";
+}
+#endif
+
+#define ZYNQMP_VERSION_SIZE	9
+
 int board_init(void)
 {
 	printf("EL Level:\tEL%d\n", current_el());
 
+#if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) && \
+    !defined(CONFIG_SPL_BUILD) || (defined(CONFIG_SPL_FPGA_SUPPORT) && \
+    defined(CONFIG_SPL_BUILD))
+	if (current_el() != 3) {
+		static char version[ZYNQMP_VERSION_SIZE];
+
+		strncat(version, "xczu", ZYNQMP_VERSION_SIZE);
+		zynqmppl.name = strncat(version,
+					zynqmp_get_silicon_idcode_name(),
+					ZYNQMP_VERSION_SIZE);
+		printf("Chip ID:\t%s\n", zynqmppl.name);
+		fpga_init();
+		fpga_add(fpga_xilinx, &zynqmppl);
+	}
+#endif
+
 	return 0;
 }
 
@@ -228,6 +328,10 @@
 
 	puts("Bootmode: ");
 	switch (bootmode) {
+	case USB_MODE:
+		puts("USB_MODE\n");
+		mode = "usb";
+		break;
 	case JTAG_MODE:
 		puts("JTAG_MODE\n");
 		mode = "pxe dhcp";
@@ -283,22 +387,38 @@
 }
 
 #ifdef CONFIG_USB_DWC3
-static struct dwc3_device dwc3_device_data = {
+static struct dwc3_device dwc3_device_data0 = {
 	.maximum_speed = USB_SPEED_HIGH,
 	.base = ZYNQMP_USB0_XHCI_BASEADDR,
 	.dr_mode = USB_DR_MODE_PERIPHERAL,
 	.index = 0,
 };
 
-int usb_gadget_handle_interrupts(void)
+static struct dwc3_device dwc3_device_data1 = {
+	.maximum_speed = USB_SPEED_HIGH,
+	.base = ZYNQMP_USB1_XHCI_BASEADDR,
+	.dr_mode = USB_DR_MODE_PERIPHERAL,
+	.index = 1,
+};
+
+int usb_gadget_handle_interrupts(int index)
 {
-	dwc3_uboot_handle_interrupt(0);
+	dwc3_uboot_handle_interrupt(index);
 	return 0;
 }
 
 int board_usb_init(int index, enum usb_init_type init)
 {
-	return dwc3_uboot_init(&dwc3_device_data);
+	debug("%s: index %x\n", __func__, index);
+
+	switch (index) {
+	case 0:
+		return dwc3_uboot_init(&dwc3_device_data0);
+	case 1:
+		return dwc3_uboot_init(&dwc3_device_data1);
+	};
+
+	return -1;
 }
 
 int board_usb_cleanup(int index, enum usb_init_type init)
diff --git a/common/board_f.c b/common/board_f.c
index da381db..9ef998f 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -290,6 +290,11 @@
 	return 0;
 }
 
+__weak int mach_cpu_init(void)
+{
+	return 0;
+}
+
 #ifdef CONFIG_SANDBOX
 static int setup_ram_buf(void)
 {
@@ -860,6 +865,7 @@
 	x86_fsp_init,
 #endif
 	arch_cpu_init,		/* basic arch cpu dependent setup */
+	mach_cpu_init,		/* SoC/machine dependent CPU setup */
 	initf_dm,
 	arch_cpu_init_dm,
 	mark_bootstage,		/* need timer, go after init dm */
diff --git a/common/image-fdt.c b/common/image-fdt.c
index d6ee225..3d23608 100644
--- a/common/image-fdt.c
+++ b/common/image-fdt.c
@@ -285,7 +285,7 @@
 			fdt_noffset = fit_get_node_from_config(images,
 							       FIT_FDT_PROP,
 							       fdt_addr);
-			if (fdt_noffset == -ENOLINK)
+			if (fdt_noffset == -ENOENT)
 				return 0;
 			else if (fdt_noffset < 0)
 				return 1;
diff --git a/common/image-fit.c b/common/image-fit.c
index 9ce68f1..1b0234a 100644
--- a/common/image-fit.c
+++ b/common/image-fit.c
@@ -1560,7 +1560,7 @@
 	cfg_noffset = fit_conf_get_node(fit_hdr, images->fit_uname_cfg);
 	if (cfg_noffset < 0) {
 		debug("*  %s: no such config\n", prop_name);
-		return -ENOENT;
+		return -EINVAL;
 	}
 
 	noffset = fit_conf_get_prop_node(fit_hdr, cfg_noffset, prop_name);
diff --git a/common/image.c b/common/image.c
index 7ad04ca..c8d9bc8 100644
--- a/common/image.c
+++ b/common/image.c
@@ -1078,7 +1078,7 @@
 			rd_addr = map_to_sysmem(images->fit_hdr_os);
 			rd_noffset = fit_get_node_from_config(images,
 					FIT_RAMDISK_PROP, rd_addr);
-			if (rd_noffset == -ENOLINK)
+			if (rd_noffset == -ENOENT)
 				return 0;
 			else if (rd_noffset < 0)
 				return 1;
diff --git a/configs/boston32r2_defconfig b/configs/boston32r2_defconfig
new file mode 100644
index 0000000..ca66248
--- /dev/null
+++ b/configs/boston32r2_defconfig
@@ -0,0 +1,41 @@
+CONFIG_MIPS=y
+CONFIG_TARGET_BOSTON=y
+CONFIG_SYS_TEXT_BASE=0x9fc00000
+# CONFIG_MIPS_BOOT_CMDLINE_LEGACY is not set
+# CONFIG_MIPS_BOOT_ENV_LEGACY is not set
+CONFIG_MIPS_BOOT_FDT=y
+CONFIG_DEFAULT_DEVICE_TREE="img,boston"
+CONFIG_FIT=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_FIT_BEST_MATCH=y
+CONFIG_OF_STDOUT_VIA_ALIAS=y
+CONFIG_HUSH_PARSER=y
+CONFIG_SYS_PROMPT="boston # "
+# CONFIG_CMD_ELF is not set
+# CONFIG_CMD_IMLS is not set
+CONFIG_CMD_GREPENV=y
+CONFIG_CMD_MEMTEST=y
+# CONFIG_CMD_LOADB is not set
+# CONFIG_CMD_LOADS is not set
+# CONFIG_CMD_FPGA is not set
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_SNTP=y
+CONFIG_CMD_DNS=y
+CONFIG_CMD_LINK_LOCAL=y
+CONFIG_CMD_TIME=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_EXT4_WRITE=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_OF_EMBED=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_CLK=y
+CONFIG_MTD=y
+CONFIG_CFI_FLASH=y
+CONFIG_DM_ETH=y
+CONFIG_PCH_GBE=y
+CONFIG_DM_PCI=y
+CONFIG_PCI_XILINX=y
+CONFIG_SYS_NS16550=y
+CONFIG_LZ4=y
diff --git a/configs/boston32r2el_defconfig b/configs/boston32r2el_defconfig
new file mode 100644
index 0000000..67f54bf
--- /dev/null
+++ b/configs/boston32r2el_defconfig
@@ -0,0 +1,42 @@
+CONFIG_MIPS=y
+CONFIG_TARGET_BOSTON=y
+CONFIG_SYS_TEXT_BASE=0x9fc00000
+CONFIG_SYS_LITTLE_ENDIAN=y
+# CONFIG_MIPS_BOOT_CMDLINE_LEGACY is not set
+# CONFIG_MIPS_BOOT_ENV_LEGACY is not set
+CONFIG_MIPS_BOOT_FDT=y
+CONFIG_DEFAULT_DEVICE_TREE="img,boston"
+CONFIG_FIT=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_FIT_BEST_MATCH=y
+CONFIG_OF_STDOUT_VIA_ALIAS=y
+CONFIG_HUSH_PARSER=y
+CONFIG_SYS_PROMPT="boston # "
+# CONFIG_CMD_ELF is not set
+# CONFIG_CMD_IMLS is not set
+CONFIG_CMD_GREPENV=y
+CONFIG_CMD_MEMTEST=y
+# CONFIG_CMD_LOADB is not set
+# CONFIG_CMD_LOADS is not set
+# CONFIG_CMD_FPGA is not set
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_SNTP=y
+CONFIG_CMD_DNS=y
+CONFIG_CMD_LINK_LOCAL=y
+CONFIG_CMD_TIME=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_EXT4_WRITE=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_OF_EMBED=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_CLK=y
+CONFIG_MTD=y
+CONFIG_CFI_FLASH=y
+CONFIG_DM_ETH=y
+CONFIG_PCH_GBE=y
+CONFIG_DM_PCI=y
+CONFIG_PCI_XILINX=y
+CONFIG_SYS_NS16550=y
+CONFIG_LZ4=y
diff --git a/configs/boston64r2_defconfig b/configs/boston64r2_defconfig
new file mode 100644
index 0000000..1245d1b
--- /dev/null
+++ b/configs/boston64r2_defconfig
@@ -0,0 +1,41 @@
+CONFIG_MIPS=y
+CONFIG_TARGET_BOSTON=y
+CONFIG_CPU_MIPS64_R2=y
+# CONFIG_MIPS_BOOT_CMDLINE_LEGACY is not set
+# CONFIG_MIPS_BOOT_ENV_LEGACY is not set
+CONFIG_MIPS_BOOT_FDT=y
+CONFIG_DEFAULT_DEVICE_TREE="img,boston"
+CONFIG_FIT=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_FIT_BEST_MATCH=y
+CONFIG_OF_STDOUT_VIA_ALIAS=y
+CONFIG_HUSH_PARSER=y
+CONFIG_SYS_PROMPT="boston # "
+# CONFIG_CMD_ELF is not set
+# CONFIG_CMD_IMLS is not set
+CONFIG_CMD_GREPENV=y
+CONFIG_CMD_MEMTEST=y
+# CONFIG_CMD_LOADB is not set
+# CONFIG_CMD_LOADS is not set
+# CONFIG_CMD_FPGA is not set
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_SNTP=y
+CONFIG_CMD_DNS=y
+CONFIG_CMD_LINK_LOCAL=y
+CONFIG_CMD_TIME=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_EXT4_WRITE=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_OF_EMBED=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_CLK=y
+CONFIG_MTD=y
+CONFIG_CFI_FLASH=y
+CONFIG_DM_ETH=y
+CONFIG_PCH_GBE=y
+CONFIG_DM_PCI=y
+CONFIG_PCI_XILINX=y
+CONFIG_SYS_NS16550=y
+CONFIG_LZ4=y
diff --git a/configs/boston64r2el_defconfig b/configs/boston64r2el_defconfig
new file mode 100644
index 0000000..9b5fa5a
--- /dev/null
+++ b/configs/boston64r2el_defconfig
@@ -0,0 +1,42 @@
+CONFIG_MIPS=y
+CONFIG_TARGET_BOSTON=y
+CONFIG_SYS_LITTLE_ENDIAN=y
+CONFIG_CPU_MIPS64_R2=y
+# CONFIG_MIPS_BOOT_CMDLINE_LEGACY is not set
+# CONFIG_MIPS_BOOT_ENV_LEGACY is not set
+CONFIG_MIPS_BOOT_FDT=y
+CONFIG_DEFAULT_DEVICE_TREE="img,boston"
+CONFIG_FIT=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_FIT_BEST_MATCH=y
+CONFIG_OF_STDOUT_VIA_ALIAS=y
+CONFIG_HUSH_PARSER=y
+CONFIG_SYS_PROMPT="boston # "
+# CONFIG_CMD_ELF is not set
+# CONFIG_CMD_IMLS is not set
+CONFIG_CMD_GREPENV=y
+CONFIG_CMD_MEMTEST=y
+# CONFIG_CMD_LOADB is not set
+# CONFIG_CMD_LOADS is not set
+# CONFIG_CMD_FPGA is not set
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_SNTP=y
+CONFIG_CMD_DNS=y
+CONFIG_CMD_LINK_LOCAL=y
+CONFIG_CMD_TIME=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_EXT4_WRITE=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_OF_EMBED=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_CLK=y
+CONFIG_MTD=y
+CONFIG_CFI_FLASH=y
+CONFIG_DM_ETH=y
+CONFIG_PCH_GBE=y
+CONFIG_DM_PCI=y
+CONFIG_PCI_XILINX=y
+CONFIG_SYS_NS16550=y
+CONFIG_LZ4=y
diff --git a/configs/imgtec_xilfpga_defconfig b/configs/imgtec_xilfpga_defconfig
new file mode 100644
index 0000000..63f03cd
--- /dev/null
+++ b/configs/imgtec_xilfpga_defconfig
@@ -0,0 +1,25 @@
+CONFIG_MIPS=y
+CONFIG_SYS_MALLOC_F_LEN=0x600
+CONFIG_TARGET_XILFPGA=y
+# CONFIG_MIPS_BOOT_ENV_LEGACY is not set
+CONFIG_MIPS_BOOT_FDT=y
+CONFIG_DEFAULT_DEVICE_TREE="nexys4ddr"
+CONFIG_BOOTDELAY=5
+CONFIG_HUSH_PARSER=y
+CONFIG_SYS_PROMPT="MIPSfpga # "
+# CONFIG_CMD_IMLS is not set
+# CONFIG_CMD_SAVEENV is not set
+CONFIG_CMD_MEMINFO=y
+# CONFIG_CMD_FLASH is not set
+# CONFIG_CMD_FPGA is not set
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_TIME=y
+CONFIG_OF_EMBED=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_NETCONSOLE=y
+CONFIG_CLK=y
+CONFIG_XILINX_EMACLITE=y
+CONFIG_SYS_NS16550=y
+CONFIG_CMD_DHRYSTONE=y
diff --git a/configs/mx6sxsabreauto_defconfig b/configs/mx6sxsabreauto_defconfig
index 41d46f6..e80bb4e 100644
--- a/configs/mx6sxsabreauto_defconfig
+++ b/configs/mx6sxsabreauto_defconfig
@@ -23,6 +23,7 @@
 CONFIG_CMD_EXT4_WRITE=y
 CONFIG_CMD_FAT=y
 CONFIG_CMD_FS_GENERIC=y
+CONFIG_FSL_QSPI=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_BAR=y
 CONFIG_SPI_FLASH_STMICRO=y
diff --git a/configs/mx6ul_14x14_evk_defconfig b/configs/mx6ul_14x14_evk_defconfig
index 9b4c4a4..a829a18 100644
--- a/configs/mx6ul_14x14_evk_defconfig
+++ b/configs/mx6ul_14x14_evk_defconfig
@@ -32,4 +32,8 @@
 CONFIG_CMD_FS_GENERIC=y
 CONFIG_USB=y
 CONFIG_USB_STORAGE=y
+CONFIG_FSL_QSPI=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_BAR=y
+CONFIG_SPI_FLASH_STMICRO=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/mx6ul_9x9_evk_defconfig b/configs/mx6ul_9x9_evk_defconfig
index e88a1dc..eaf3cfd 100644
--- a/configs/mx6ul_9x9_evk_defconfig
+++ b/configs/mx6ul_9x9_evk_defconfig
@@ -32,4 +32,8 @@
 CONFIG_CMD_FS_GENERIC=y
 CONFIG_USB=y
 CONFIG_USB_STORAGE=y
+CONFIG_FSL_QSPI=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_BAR=y
+CONFIG_SPI_FLASH_STMICRO=y
 CONFIG_OF_LIBFDT=y
diff --git a/configs/omap4_panda_defconfig b/configs/omap4_panda_defconfig
index af6dc31..e496afe 100644
--- a/configs/omap4_panda_defconfig
+++ b/configs/omap4_panda_defconfig
@@ -1,5 +1,6 @@
 CONFIG_ARM=y
 CONFIG_OMAP44XX=y
+# CONFIG_SPL_EXT_SUPPORT is not set
 # CONFIG_SPL_I2C_SUPPORT is not set
 # CONFIG_SPL_NAND_SUPPORT is not set
 CONFIG_TARGET_OMAP4_PANDA=y
diff --git a/configs/uniphier_ld11_defconfig b/configs/uniphier_ld11_defconfig
index f6578c1..864e04e 100644
--- a/configs/uniphier_ld11_defconfig
+++ b/configs/uniphier_ld11_defconfig
@@ -1,6 +1,7 @@
 CONFIG_ARM=y
 CONFIG_ARCH_UNIPHIER=y
 CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_ARCH_UNIPHIER_LD11=y
 CONFIG_MICRO_SUPPORT_CARD=y
 CONFIG_SYS_TEXT_BASE=0x84000000
diff --git a/configs/uniphier_ld20_defconfig b/configs/uniphier_ld20_defconfig
index b85f528..3fe3758 100644
--- a/configs/uniphier_ld20_defconfig
+++ b/configs/uniphier_ld20_defconfig
@@ -1,6 +1,7 @@
 CONFIG_ARM=y
 CONFIG_ARCH_UNIPHIER=y
 CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_ARCH_UNIPHIER_LD20=y
 CONFIG_MICRO_SUPPORT_CARD=y
 CONFIG_SYS_TEXT_BASE=0x84000000
diff --git a/configs/uniphier_ld4_sld8_defconfig b/configs/uniphier_ld4_sld8_defconfig
index e996355..c18f042 100644
--- a/configs/uniphier_ld4_sld8_defconfig
+++ b/configs/uniphier_ld4_sld8_defconfig
@@ -1,6 +1,9 @@
 CONFIG_ARM=y
 CONFIG_ARCH_UNIPHIER=y
 CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_SPL_MMC_SUPPORT=y
+CONFIG_SPL_NAND_SUPPORT=y
+CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_ARCH_UNIPHIER_LD4_SLD8=y
 CONFIG_MICRO_SUPPORT_CARD=y
 CONFIG_SYS_TEXT_BASE=0x84000000
diff --git a/configs/uniphier_pro4_defconfig b/configs/uniphier_pro4_defconfig
index f0f47ee..9441b05 100644
--- a/configs/uniphier_pro4_defconfig
+++ b/configs/uniphier_pro4_defconfig
@@ -1,6 +1,9 @@
 CONFIG_ARM=y
 CONFIG_ARCH_UNIPHIER=y
 CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_SPL_MMC_SUPPORT=y
+CONFIG_SPL_NAND_SUPPORT=y
+CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_MICRO_SUPPORT_CARD=y
 CONFIG_SYS_TEXT_BASE=0x84000000
 CONFIG_DEFAULT_DEVICE_TREE="uniphier-ph1-pro4-ref"
diff --git a/configs/uniphier_pxs2_ld6b_defconfig b/configs/uniphier_pxs2_ld6b_defconfig
index 64684de..0bf39f4 100644
--- a/configs/uniphier_pxs2_ld6b_defconfig
+++ b/configs/uniphier_pxs2_ld6b_defconfig
@@ -1,6 +1,9 @@
 CONFIG_ARM=y
 CONFIG_ARCH_UNIPHIER=y
 CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_SPL_MMC_SUPPORT=y
+CONFIG_SPL_NAND_SUPPORT=y
+CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_ARCH_UNIPHIER_PRO5_PXS2_LD6B=y
 CONFIG_MICRO_SUPPORT_CARD=y
 CONFIG_SYS_TEXT_BASE=0x84000000
diff --git a/configs/uniphier_sld3_defconfig b/configs/uniphier_sld3_defconfig
index f4ed2ee..bd9c327 100644
--- a/configs/uniphier_sld3_defconfig
+++ b/configs/uniphier_sld3_defconfig
@@ -1,6 +1,9 @@
 CONFIG_ARM=y
 CONFIG_ARCH_UNIPHIER=y
 CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_SPL_MMC_SUPPORT=y
+CONFIG_SPL_NAND_SUPPORT=y
+CONFIG_SPL_SERIAL_SUPPORT=y
 CONFIG_ARCH_UNIPHIER_SLD3=y
 CONFIG_MICRO_SUPPORT_CARD=y
 CONFIG_SYS_TEXT_BASE=0x84000000
diff --git a/configs/xilinx_zynqmp_ep_defconfig b/configs/xilinx_zynqmp_ep_defconfig
index 196eb69..bd8b906 100644
--- a/configs/xilinx_zynqmp_ep_defconfig
+++ b/configs/xilinx_zynqmp_ep_defconfig
@@ -5,6 +5,7 @@
 CONFIG_ZYNQMP_USB=y
 CONFIG_SYS_TEXT_BASE=0x8000000
 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-ep108"
+CONFIG_AHCI=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_SPL_LOAD_FIT=y
@@ -46,6 +47,8 @@
 CONFIG_SPL_DM=y
 CONFIG_SPL_DM_SEQ_ALIAS=y
 CONFIG_BLK=y
+CONFIG_FPGA_XILINX=y
+CONFIG_FPGA_ZYNQMPPL=y
 CONFIG_DM_GPIO=y
 CONFIG_DM_I2C=y
 CONFIG_SYS_I2C_CADENCE=y
diff --git a/configs/xilinx_zynqmp_zc1751_xm015_dc1_defconfig b/configs/xilinx_zynqmp_zc1751_xm015_dc1_defconfig
index a3fb226..6afacd2 100644
--- a/configs/xilinx_zynqmp_zc1751_xm015_dc1_defconfig
+++ b/configs/xilinx_zynqmp_zc1751_xm015_dc1_defconfig
@@ -38,6 +38,8 @@
 CONFIG_SPL_DM=y
 CONFIG_SPL_DM_SEQ_ALIAS=y
 CONFIG_BLK=y
+CONFIG_FPGA_XILINX=y
+CONFIG_FPGA_ZYNQMPPL=y
 CONFIG_DM_GPIO=y
 CONFIG_DM_I2C=y
 CONFIG_SYS_I2C_CADENCE=y
diff --git a/configs/xilinx_zynqmp_zc1751_xm016_dc2_defconfig b/configs/xilinx_zynqmp_zc1751_xm016_dc2_defconfig
index aec4f9b..4068c28 100644
--- a/configs/xilinx_zynqmp_zc1751_xm016_dc2_defconfig
+++ b/configs/xilinx_zynqmp_zc1751_xm016_dc2_defconfig
@@ -41,6 +41,8 @@
 CONFIG_SPL_DM=y
 CONFIG_SPL_DM_SEQ_ALIAS=y
 CONFIG_BLK=y
+CONFIG_FPGA_XILINX=y
+CONFIG_FPGA_ZYNQMPPL=y
 CONFIG_DM_GPIO=y
 CONFIG_DM_I2C=y
 CONFIG_SYS_I2C_CADENCE=y
diff --git a/configs/xilinx_zynqmp_zc1751_xm018_dc4_defconfig b/configs/xilinx_zynqmp_zc1751_xm018_dc4_defconfig
index 0b2ebb1..c717f04 100644
--- a/configs/xilinx_zynqmp_zc1751_xm018_dc4_defconfig
+++ b/configs/xilinx_zynqmp_zc1751_xm018_dc4_defconfig
@@ -1,5 +1,4 @@
 CONFIG_ARM=y
-CONFIG_SYS_CONFIG_NAME="xilinx_zynqmp_zc1751_xm018_dc4"
 CONFIG_ARCH_ZYNQMP=y
 CONFIG_SYS_MALLOC_F_LEN=0x8000
 CONFIG_IDENT_STRING=" Xilinx ZynqMP ZC1751 xm018 dc4"
@@ -34,6 +33,8 @@
 CONFIG_SPL_DM=y
 CONFIG_SPL_DM_SEQ_ALIAS=y
 CONFIG_BLK=y
+CONFIG_FPGA_XILINX=y
+CONFIG_FPGA_ZYNQMPPL=y
 CONFIG_DM_GPIO=y
 CONFIG_DM_I2C=y
 CONFIG_SYS_I2C_CADENCE=y
diff --git a/configs/xilinx_zynqmp_zc1751_xm019_dc5_defconfig b/configs/xilinx_zynqmp_zc1751_xm019_dc5_defconfig
index f570b2a..1a27bd0 100644
--- a/configs/xilinx_zynqmp_zc1751_xm019_dc5_defconfig
+++ b/configs/xilinx_zynqmp_zc1751_xm019_dc5_defconfig
@@ -33,6 +33,8 @@
 CONFIG_SPL_DM=y
 CONFIG_SPL_DM_SEQ_ALIAS=y
 CONFIG_BLK=y
+CONFIG_FPGA_XILINX=y
+CONFIG_FPGA_ZYNQMPPL=y
 CONFIG_DM_GPIO=y
 CONFIG_DM_I2C=y
 CONFIG_SYS_I2C_CADENCE=y
diff --git a/configs/xilinx_zynqmp_zcu102_defconfig b/configs/xilinx_zynqmp_zcu102_defconfig
index 8fcb2fd..90b5ff6 100644
--- a/configs/xilinx_zynqmp_zcu102_defconfig
+++ b/configs/xilinx_zynqmp_zcu102_defconfig
@@ -6,6 +6,7 @@
 CONFIG_IDENT_STRING=" Xilinx ZynqMP ZCU102"
 CONFIG_SYS_TEXT_BASE=0x8000000
 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zcu102"
+CONFIG_AHCI=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_SPL_LOAD_FIT=y
@@ -38,6 +39,8 @@
 CONFIG_SPL_DM=y
 CONFIG_SPL_DM_SEQ_ALIAS=y
 CONFIG_BLK=y
+CONFIG_FPGA_XILINX=y
+CONFIG_FPGA_ZYNQMPPL=y
 CONFIG_DM_GPIO=y
 CONFIG_DM_MMC=y
 CONFIG_DM_MMC_OPS=y
diff --git a/configs/xilinx_zynqmp_zcu102_revB_defconfig b/configs/xilinx_zynqmp_zcu102_revB_defconfig
index b7ba599..5a0d686 100644
--- a/configs/xilinx_zynqmp_zcu102_revB_defconfig
+++ b/configs/xilinx_zynqmp_zcu102_revB_defconfig
@@ -6,6 +6,7 @@
 CONFIG_IDENT_STRING=" Xilinx ZynqMP ZCU102"
 CONFIG_SYS_TEXT_BASE=0x8000000
 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zcu102-revB"
+CONFIG_AHCI=y
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
 CONFIG_SPL_LOAD_FIT=y
@@ -38,6 +39,8 @@
 CONFIG_SPL_DM=y
 CONFIG_SPL_DM_SEQ_ALIAS=y
 CONFIG_BLK=y
+CONFIG_FPGA_XILINX=y
+CONFIG_FPGA_ZYNQMPPL=y
 CONFIG_DM_GPIO=y
 CONFIG_DM_MMC=y
 CONFIG_DM_MMC_OPS=y
diff --git a/doc/README.boston b/doc/README.boston
new file mode 100644
index 0000000..38f6710
--- /dev/null
+++ b/doc/README.boston
@@ -0,0 +1,58 @@
+MIPS Boston Development Board
+
+---------
+  About
+---------
+
+The MIPS Boston development board is built around an FPGA & 3 PCIe controllers,
+one of which is connected to an Intel EG20T Platform Controller Hub which
+provides most connectivity to the board. It is used during the development &
+testing of both new CPUs and the software support for them. It is essentially
+the successor of the older MIPS Malta board.
+
+--------
+  QEMU
+--------
+
+U-Boot can be run on a currently out-of-tree branch of QEMU with support for
+the Boston board added. This QEMU code can currently be found in the "boston"
+branch of git://git.linux-mips.org/pub/scm/paul/qemu.git and used like so:
+
+  $ git clone git://git.linux-mips.org/pub/scm/paul/qemu.git -b boston
+  $ cd qemu
+  $ ./configure --target-list=mips64el-softmmu
+  $ make
+  $ ./mips64el-softmmu/qemu-system-mips64el -M boston -m 2G \
+      -bios u-boot.bin -serial stdio
+
+Please note that QEMU will default to emulating the I6400 CPU which implements
+the MIPS64r6 ISA, and at the time of writing doesn't implement any earlier CPUs
+with support for the CPS features the Boston board relies upon. You will
+therefore need to configure U-Boot to build for MIPSr6 in order to obtain a
+binary that will work in QEMU.
+
+-------------
+  Toolchain
+-------------
+
+If building for MIPSr6 then you will need a toolchain including GCC 5.x or
+newer, or the Codescape toolchain available for download from Imagination
+Technologies:
+
+  http://codescape-mips-sdk.imgtec.com/components/toolchain/2015.06-05/
+
+The "IMG GNU Linux Toolchain" is capable of building for all current MIPS ISAs,
+architecture revisions & both endiannesses.
+
+--------
+  TODO
+--------
+
+  - AHCI support
+  - CPU driver
+  - Exception handling (+UHI?)
+  - Flash support
+  - IOCU support
+  - L2 cache support
+  - More general LCD display driver
+  - Multi-arch-variant multi-endian fat binary
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 4f84469..4c555a0 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -20,6 +20,8 @@
 
 source "drivers/dma/Kconfig"
 
+source "drivers/fpga/Kconfig"
+
 source "drivers/gpio/Kconfig"
 
 source "drivers/hwmon/Kconfig"
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 8f3b96a..c05ce2a 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -20,6 +20,14 @@
 	  setting up clocks within SPL, and allows the same drivers to be
 	  used as U-Boot proper.
 
+config CLK_BOSTON
+	def_bool y if TARGET_BOSTON
+	depends on CLK
+	select REGMAP
+	select SYSCON
+	help
+	  Enable this to support the clocks
+
 source "drivers/clk/tegra/Kconfig"
 source "drivers/clk/uniphier/Kconfig"
 source "drivers/clk/exynos/Kconfig"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 778d748..40a5e8c 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -15,3 +15,4 @@
 obj-$(CONFIG_CLK_UNIPHIER) += uniphier/
 obj-$(CONFIG_CLK_EXYNOS) += exynos/
 obj-$(CONFIG_CLK_AT91) += at91/
+obj-$(CONFIG_CLK_BOSTON) += clk_boston.o
diff --git a/drivers/clk/clk_boston.c b/drivers/clk/clk_boston.c
new file mode 100644
index 0000000..78f1b75
--- /dev/null
+++ b/drivers/clk/clk_boston.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2016 Imagination Technologies
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <dt-bindings/clock/boston-clock.h>
+#include <regmap.h>
+#include <syscon.h>
+
+struct clk_boston {
+	struct regmap *regmap;
+};
+
+#define BOSTON_PLAT_MMCMDIV		0x30
+# define BOSTON_PLAT_MMCMDIV_CLK0DIV	(0xff << 0)
+# define BOSTON_PLAT_MMCMDIV_INPUT	(0xff << 8)
+# define BOSTON_PLAT_MMCMDIV_MUL	(0xff << 16)
+# define BOSTON_PLAT_MMCMDIV_CLK1DIV	(0xff << 24)
+
+static uint32_t ext_field(uint32_t val, uint32_t mask)
+{
+	return (val & mask) >> (ffs(mask) - 1);
+}
+
+static ulong clk_boston_get_rate(struct clk *clk)
+{
+	struct clk_boston *state = dev_get_platdata(clk->dev);
+	uint32_t in_rate, mul, div;
+	uint mmcmdiv;
+	int err;
+
+	err = regmap_read(state->regmap, BOSTON_PLAT_MMCMDIV, &mmcmdiv);
+	if (err)
+		return 0;
+
+	in_rate = ext_field(mmcmdiv, BOSTON_PLAT_MMCMDIV_INPUT);
+	mul = ext_field(mmcmdiv, BOSTON_PLAT_MMCMDIV_MUL);
+
+	switch (clk->id) {
+	case BOSTON_CLK_SYS:
+		div = ext_field(mmcmdiv, BOSTON_PLAT_MMCMDIV_CLK0DIV);
+		break;
+	case BOSTON_CLK_CPU:
+		div = ext_field(mmcmdiv, BOSTON_PLAT_MMCMDIV_CLK1DIV);
+		break;
+	default:
+		return 0;
+	}
+
+	return (in_rate * mul * 1000000) / div;
+}
+
+const struct clk_ops clk_boston_ops = {
+	.get_rate = clk_boston_get_rate,
+};
+
+static int clk_boston_ofdata_to_platdata(struct udevice *dev)
+{
+	struct clk_boston *state = dev_get_platdata(dev);
+	struct udevice *syscon;
+	int err;
+
+	err = uclass_get_device_by_phandle(UCLASS_SYSCON, dev,
+					   "regmap", &syscon);
+	if (err) {
+		error("unable to find syscon device\n");
+		return err;
+	}
+
+	state->regmap = syscon_get_regmap(syscon);
+	if (!state->regmap) {
+		error("unable to find regmap\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static const struct udevice_id clk_boston_match[] = {
+	{
+		.compatible = "img,boston-clock",
+	},
+	{ /* sentinel */ }
+};
+
+U_BOOT_DRIVER(clk_boston) = {
+	.name = "boston_clock",
+	.id = UCLASS_CLK,
+	.of_match = clk_boston_match,
+	.ofdata_to_platdata = clk_boston_ofdata_to_platdata,
+	.platdata_auto_alloc_size = sizeof(struct clk_boston),
+	.ops = &clk_boston_ops,
+};
diff --git a/drivers/clk/uniphier/clk-uniphier-core.c b/drivers/clk/uniphier/clk-uniphier-core.c
index a91924e..3948326 100644
--- a/drivers/clk/uniphier/clk-uniphier-core.c
+++ b/drivers/clk/uniphier/clk-uniphier-core.c
@@ -14,10 +14,39 @@
 
 #include "clk-uniphier.h"
 
+/**
+ * struct uniphier_clk_priv - private data for UniPhier clock driver
+ *
+ * @base: base address of the clock provider
+ * @socdata: SoC specific data
+ */
+struct uniphier_clk_priv {
+	void __iomem *base;
+	const struct uniphier_clk_soc_data *socdata;
+};
+
+int uniphier_clk_probe(struct udevice *dev)
+{
+	struct uniphier_clk_priv *priv = dev_get_priv(dev);
+	fdt_addr_t addr;
+
+	addr = dev_get_addr(dev->parent);
+	if (addr == FDT_ADDR_T_NONE)
+		return -EINVAL;
+
+	priv->base = devm_ioremap(dev, addr, SZ_4K);
+	if (!priv->base)
+		return -ENOMEM;
+
+	priv->socdata = (void *)dev_get_driver_data(dev);
+
+	return 0;
+}
+
 static int uniphier_clk_enable(struct clk *clk)
 {
 	struct uniphier_clk_priv *priv = dev_get_priv(clk->dev);
-	struct uniphier_clk_gate_data *gate = priv->socdata->gate;
+	const struct uniphier_clk_gate_data *gate = priv->socdata->gate;
 	unsigned int nr_gate = priv->socdata->nr_gate;
 	void __iomem *reg;
 	u32 mask, data, tmp;
@@ -44,7 +73,7 @@
 static ulong uniphier_clk_get_rate(struct clk *clk)
 {
 	struct uniphier_clk_priv *priv = dev_get_priv(clk->dev);
-	struct uniphier_clk_rate_data *rdata = priv->socdata->rate;
+	const struct uniphier_clk_rate_data *rdata = priv->socdata->rate;
 	unsigned int nr_rdata = priv->socdata->nr_rate;
 	void __iomem *reg;
 	u32 mask, data;
@@ -78,7 +107,7 @@
 static ulong uniphier_clk_set_rate(struct clk *clk, ulong rate)
 {
 	struct uniphier_clk_priv *priv = dev_get_priv(clk->dev);
-	struct uniphier_clk_rate_data *rdata = priv->socdata->rate;
+	const struct uniphier_clk_rate_data *rdata = priv->socdata->rate;
 	unsigned int nr_rdata = priv->socdata->nr_rate;
 	void __iomem *reg;
 	u32 mask, data, tmp;
@@ -128,20 +157,47 @@
 	.set_rate = uniphier_clk_set_rate,
 };
 
-int uniphier_clk_probe(struct udevice *dev)
-{
-	struct uniphier_clk_priv *priv = dev_get_priv(dev);
-	fdt_addr_t addr;
-
-	addr = dev_get_addr(dev);
-	if (addr == FDT_ADDR_T_NONE)
-		return -EINVAL;
-
-	priv->base = devm_ioremap(dev, addr, SZ_4K);
-	if (!priv->base)
-		return -ENOMEM;
-
-	priv->socdata = (void *)dev_get_driver_data(dev);
+static const struct udevice_id uniphier_clk_match[] = {
+	{
+		.compatible = "socionext,uniphier-sld3-mio-clock",
+		.data = (ulong)&uniphier_mio_clk_data,
+	},
+	{
+		.compatible = "socionext,uniphier-ld4-mio-clock",
+		.data = (ulong)&uniphier_mio_clk_data,
+	},
+	{
+		.compatible = "socionext,uniphier-pro4-mio-clock",
+		.data = (ulong)&uniphier_mio_clk_data,
+	},
+	{
+		.compatible = "socionext,uniphier-sld8-mio-clock",
+		.data = (ulong)&uniphier_mio_clk_data,
+	},
+	{
+		.compatible = "socionext,uniphier-pro5-mio-clock",
+		.data = (ulong)&uniphier_mio_clk_data,
+	},
+	{
+		.compatible = "socionext,uniphier-pxs2-mio-clock",
+		.data = (ulong)&uniphier_mio_clk_data,
+	},
+	{
+		.compatible = "socionext,uniphier-ld11-mio-clock",
+		.data = (ulong)&uniphier_mio_clk_data,
+	},
+	{
+		.compatible = "socionext,uniphier-ld20-mio-clock",
+		.data = (ulong)&uniphier_mio_clk_data,
+	},
+	{ /* sentinel */ }
+};
 
-	return 0;
-}
+U_BOOT_DRIVER(uniphier_clk) = {
+	.name = "uniphier-clk",
+	.id = UCLASS_CLK,
+	.of_match = uniphier_clk_match,
+	.probe = uniphier_clk_probe,
+	.priv_auto_alloc_size = sizeof(struct uniphier_clk_priv),
+	.ops = &uniphier_clk_ops,
+};
diff --git a/drivers/clk/uniphier/clk-uniphier-mio.c b/drivers/clk/uniphier/clk-uniphier-mio.c
index 2eea5eb..c1e7197 100644
--- a/drivers/clk/uniphier/clk-uniphier-mio.c
+++ b/drivers/clk/uniphier/clk-uniphier-mio.c
@@ -115,7 +115,7 @@
 		.data = 0x00020000,		\
 	}
 
-static struct uniphier_clk_gate_data uniphier_mio_clk_gate[] = {
+static const struct uniphier_clk_gate_data uniphier_mio_clk_gate[] = {
 	UNIPHIER_MIO_CLK_GATE_SD(0, 0),
 	UNIPHIER_MIO_CLK_GATE_SD(1, 1),
 	UNIPHIER_MIO_CLK_GATE_SD(2, 2),		/* for PH1-Pro4 only */
@@ -126,60 +126,15 @@
 	UNIPHIER_MIO_CLK_GATE_USB(3, 7),	/* for PH1-sLD3 only */
 };
 
-static struct uniphier_clk_rate_data uniphier_mio_clk_rate[] = {
+static const struct uniphier_clk_rate_data uniphier_mio_clk_rate[] = {
 	UNIPHIER_MIO_CLK_RATE_SD(0, 0),
 	UNIPHIER_MIO_CLK_RATE_SD(1, 1),
 	UNIPHIER_MIO_CLK_RATE_SD(2, 2),		/* for PH1-Pro4 only */
 };
 
-static struct uniphier_clk_soc_data uniphier_mio_clk_data = {
+const struct uniphier_clk_soc_data uniphier_mio_clk_data = {
 	.gate = uniphier_mio_clk_gate,
 	.nr_gate = ARRAY_SIZE(uniphier_mio_clk_gate),
 	.rate = uniphier_mio_clk_rate,
 	.nr_rate = ARRAY_SIZE(uniphier_mio_clk_rate),
 };
-
-static const struct udevice_id uniphier_mio_clk_match[] = {
-	{
-		.compatible = "socionext,ph1-sld3-mioctrl",
-		.data = (ulong)&uniphier_mio_clk_data,
-	},
-	{
-		.compatible = "socionext,ph1-ld4-mioctrl",
-		.data = (ulong)&uniphier_mio_clk_data,
-	},
-	{
-		.compatible = "socionext,ph1-pro4-mioctrl",
-		.data = (ulong)&uniphier_mio_clk_data,
-	},
-	{
-		.compatible = "socionext,ph1-sld8-mioctrl",
-		.data = (ulong)&uniphier_mio_clk_data,
-	},
-	{
-		.compatible = "socionext,ph1-pro5-mioctrl",
-		.data = (ulong)&uniphier_mio_clk_data,
-	},
-	{
-		.compatible = "socionext,proxstream2-mioctrl",
-		.data = (ulong)&uniphier_mio_clk_data,
-	},
-	{
-		.compatible = "socionext,ph1-ld11-mioctrl",
-		.data = (ulong)&uniphier_mio_clk_data,
-	},
-	{
-		.compatible = "socionext,ph1-ld20-mioctrl",
-		.data = (ulong)&uniphier_mio_clk_data,
-	},
-	{ /* sentinel */ }
-};
-
-U_BOOT_DRIVER(uniphier_mio_clk) = {
-	.name = "uniphier-mio-clk",
-	.id = UCLASS_CLK,
-	.of_match = uniphier_mio_clk_match,
-	.probe = uniphier_clk_probe,
-	.priv_auto_alloc_size = sizeof(struct uniphier_clk_priv),
-	.ops = &uniphier_clk_ops,
-};
diff --git a/drivers/clk/uniphier/clk-uniphier.h b/drivers/clk/uniphier/clk-uniphier.h
index 18aa888..0b60337 100644
--- a/drivers/clk/uniphier/clk-uniphier.h
+++ b/drivers/clk/uniphier/clk-uniphier.h
@@ -27,9 +27,9 @@
 };
 
 struct uniphier_clk_soc_data {
-	struct uniphier_clk_gate_data *gate;
+	const struct uniphier_clk_gate_data *gate;
 	unsigned int nr_gate;
-	struct uniphier_clk_rate_data *rate;
+	const struct uniphier_clk_rate_data *rate;
 	unsigned int nr_rate;
 };
 
@@ -40,18 +40,6 @@
 		.rate = f,				\
 	}
 
-/**
- * struct uniphier_clk_priv - private data for UniPhier clock driver
- *
- * @base: base address of the clock provider
- * @socdata: SoC specific data
- */
-struct uniphier_clk_priv {
-	void __iomem *base;
-	struct uniphier_clk_soc_data *socdata;
-};
-
-extern const struct clk_ops uniphier_clk_ops;
-int uniphier_clk_probe(struct udevice *dev);
+extern const struct uniphier_clk_soc_data uniphier_mio_clk_data;
 
 #endif /* __CLK_UNIPHIER_H__ */
diff --git a/drivers/core/lists.c b/drivers/core/lists.c
index 6a634e6..23b6ba7 100644
--- a/drivers/core/lists.c
+++ b/drivers/core/lists.c
@@ -101,36 +101,24 @@
 
 #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
 /**
- * driver_check_compatible() - Check if a driver is compatible with this node
+ * driver_check_compatible() - Check if a driver matches a compatible string
  *
- * @param blob:		Device tree pointer
- * @param offset:	Offset of node in device tree
  * @param of_match:	List of compatible strings to match
  * @param of_idp:	Returns the match that was found
- * @return 0 if there is a match, -ENOENT if no match, -ENODEV if the node
- * does not have a compatible string, other error <0 if there is a device
- * tree error
+ * @param compat:	The compatible string to search for
+ * @return 0 if there is a match, -ENOENT if no match
  */
-static int driver_check_compatible(const void *blob, int offset,
-				   const struct udevice_id *of_match,
-				   const struct udevice_id **of_idp)
+static int driver_check_compatible(const struct udevice_id *of_match,
+				   const struct udevice_id **of_idp,
+				   const char *compat)
 {
-	int ret;
-
-	*of_idp = NULL;
 	if (!of_match)
 		return -ENOENT;
 
 	while (of_match->compatible) {
-		ret = fdt_node_check_compatible(blob, offset,
-						of_match->compatible);
-		if (!ret) {
+		if (!strcmp(of_match->compatible, compat)) {
 			*of_idp = of_match;
 			return 0;
-		} else if (ret == -FDT_ERR_NOTFOUND) {
-			return -ENODEV;
-		} else if (ret < 0) {
-			return -EINVAL;
 		}
 		of_match++;
 	}
@@ -147,28 +135,46 @@
 	struct driver *entry;
 	struct udevice *dev;
 	bool found = false;
-	const char *name;
+	const char *name, *compat_list, *compat;
+	int compat_length, i;
 	int result = 0;
 	int ret = 0;
 
-	dm_dbg("bind node %s\n", fdt_get_name(blob, offset, NULL));
+	name = fdt_get_name(blob, offset, NULL);
+	dm_dbg("bind node %s\n", name);
 	if (devp)
 		*devp = NULL;
-	for (entry = driver; entry != driver + n_ents; entry++) {
-		ret = driver_check_compatible(blob, offset, entry->of_match,
-					      &id);
-		name = fdt_get_name(blob, offset, NULL);
-		if (ret == -ENOENT) {
-			continue;
-		} else if (ret == -ENODEV) {
+
+	compat_list = fdt_getprop(blob, offset, "compatible", &compat_length);
+	if (!compat_list) {
+		if (compat_length == -FDT_ERR_NOTFOUND) {
 			dm_dbg("Device '%s' has no compatible string\n", name);
-			break;
-		} else if (ret) {
-			dm_warn("Device tree error at offset %d\n", offset);
-			result = ret;
-			break;
+			return 0;
 		}
 
+		dm_warn("Device tree error at offset %d\n", offset);
+		return compat_length;
+	}
+
+	/*
+	 * Walk through the compatible string list, attempting to match each
+	 * compatible string in order such that we match in order of priority
+	 * from the first string to the last.
+	 */
+	for (i = 0; i < compat_length; i += strlen(compat) + 1) {
+		compat = compat_list + i;
+		dm_dbg("   - attempt to match compatible string '%s'\n",
+		       compat);
+
+		for (entry = driver; entry != driver + n_ents; entry++) {
+			ret = driver_check_compatible(entry->of_match, &id,
+						      compat);
+			if (!ret)
+				break;
+		}
+		if (entry == driver + n_ents)
+			continue;
+
 		dm_dbg("   - found match at '%s'\n", entry->name);
 		ret = device_bind_with_driver_data(parent, entry, name,
 						   id->data, offset, &dev);
@@ -188,10 +194,8 @@
 		break;
 	}
 
-	if (!found && !result && ret != -ENODEV) {
-		dm_dbg("No match for node '%s'\n",
-		       fdt_get_name(blob, offset, NULL));
-	}
+	if (!found && !result && ret != -ENODEV)
+		dm_dbg("No match for node '%s'\n", name);
 
 	return result;
 }
diff --git a/drivers/core/regmap.c b/drivers/core/regmap.c
index 0299ff0..c68bcba 100644
--- a/drivers/core/regmap.c
+++ b/drivers/core/regmap.c
@@ -13,6 +13,8 @@
 #include <mapmem.h>
 #include <regmap.h>
 
+#include <asm/io.h>
+
 DECLARE_GLOBAL_DATA_PTR;
 
 static struct regmap *regmap_alloc_count(int count)
@@ -117,3 +119,21 @@
 
 	return 0;
 }
+
+int regmap_read(struct regmap *map, uint offset, uint *valp)
+{
+	uint32_t *ptr = map_physmem(map->base + offset, 4, MAP_NOCACHE);
+
+	*valp = le32_to_cpu(readl(ptr));
+
+	return 0;
+}
+
+int regmap_write(struct regmap *map, uint offset, uint val)
+{
+	uint32_t *ptr = map_physmem(map->base + offset, 4, MAP_NOCACHE);
+
+	writel(cpu_to_le32(val), ptr);
+
+	return 0;
+}
diff --git a/drivers/core/syscon-uclass.c b/drivers/core/syscon-uclass.c
index 01bd968..2148469 100644
--- a/drivers/core/syscon-uclass.c
+++ b/drivers/core/syscon-uclass.c
@@ -95,3 +95,14 @@
 	.per_device_auto_alloc_size = sizeof(struct syscon_uc_info),
 	.pre_probe = syscon_pre_probe,
 };
+
+static const struct udevice_id generic_syscon_ids[] = {
+	{ .compatible = "syscon" },
+	{ }
+};
+
+U_BOOT_DRIVER(generic_syscon) = {
+	.name	= "syscon",
+	.id	= UCLASS_SYSCON,
+	.of_match = generic_syscon_ids,
+};
diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
new file mode 100644
index 0000000..f3f6bf7
--- /dev/null
+++ b/drivers/fpga/Kconfig
@@ -0,0 +1,20 @@
+menu "FPGA support"
+
+config FPGA
+	bool
+
+config FPGA_XILINX
+	bool "Enable Xilinx FPGA drivers"
+	select FPGA
+	help
+	  Enable Xilinx FPGA specific functions which includes bitstream
+	  (in BIT format), fpga and device validation.
+
+config FPGA_ZYNQMPPL
+	bool "Enable Xilinx FPGA driver for ZynqMP"
+	depends on FPGA_XILINX
+	help
+	  Enable FPGA driver for loading bitstream in BIT and BIN format
+	  on Xilinx Zynq UltraScale+ (ZynqMP) device.
+
+endmenu
diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
index fec3fec..777706f 100644
--- a/drivers/fpga/Makefile
+++ b/drivers/fpga/Makefile
@@ -10,6 +10,7 @@
 obj-$(CONFIG_FPGA_SPARTAN3) += spartan3.o
 obj-$(CONFIG_FPGA_VIRTEX2) += virtex2.o
 obj-$(CONFIG_FPGA_ZYNQPL) += zynqpl.o
+obj-$(CONFIG_FPGA_ZYNQMPPL) += zynqmppl.o
 obj-$(CONFIG_FPGA_XILINX) += xilinx.o
 obj-$(CONFIG_FPGA_LATTICE) += ivm_core.o lattice.o
 ifdef CONFIG_FPGA_ALTERA
diff --git a/drivers/fpga/xilinx.c b/drivers/fpga/xilinx.c
index d459a2f..2cd0104 100644
--- a/drivers/fpga/xilinx.c
+++ b/drivers/fpga/xilinx.c
@@ -199,6 +199,9 @@
 		case xilinx_zynq:
 			printf("Zynq PL\n");
 			break;
+		case xilinx_zynqmp:
+			printf("ZynqMP PL\n");
+			break;
 			/* Add new family types here */
 		default:
 			printf ("Unknown family type, %d\n", desc->family);
@@ -227,6 +230,9 @@
 		case devcfg:
 			printf("Device configuration interface (Zynq)\n");
 			break;
+		case csu_dma:
+			printf("csu_dma configuration interface (ZynqMP)\n");
+			break;
 			/* Add new interface types here */
 		default:
 			printf ("Unsupported interface type, %d\n", desc->iface);
diff --git a/drivers/fpga/zynqmppl.c b/drivers/fpga/zynqmppl.c
new file mode 100644
index 0000000..23039c3
--- /dev/null
+++ b/drivers/fpga/zynqmppl.c
@@ -0,0 +1,238 @@
+/*
+ * (C) Copyright 2015 - 2016, Xilinx, Inc,
+ * Michal Simek <michal.simek@xilinx.com>
+ * Siva Durga Prasad <siva.durga.paladugu@xilinx.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <console.h>
+#include <common.h>
+#include <zynqmppl.h>
+#include <linux/sizes.h>
+
+#define DUMMY_WORD	0xffffffff
+
+/* Xilinx binary format header */
+static const u32 bin_format[] = {
+	DUMMY_WORD, /* Dummy words */
+	DUMMY_WORD,
+	DUMMY_WORD,
+	DUMMY_WORD,
+	DUMMY_WORD,
+	DUMMY_WORD,
+	DUMMY_WORD,
+	DUMMY_WORD,
+	DUMMY_WORD,
+	DUMMY_WORD,
+	DUMMY_WORD,
+	DUMMY_WORD,
+	DUMMY_WORD,
+	DUMMY_WORD,
+	DUMMY_WORD,
+	DUMMY_WORD,
+	0x000000bb, /* Sync word */
+	0x11220044, /* Sync word */
+	DUMMY_WORD,
+	DUMMY_WORD,
+	0xaa995566, /* Sync word */
+};
+
+#define SWAP_NO		1
+#define SWAP_DONE	2
+
+/*
+ * Load the whole word from unaligned buffer
+ * Keep in your mind that it is byte loading on little-endian system
+ */
+static u32 load_word(const void *buf, u32 swap)
+{
+	u32 word = 0;
+	u8 *bitc = (u8 *)buf;
+	int p;
+
+	if (swap == SWAP_NO) {
+		for (p = 0; p < 4; p++) {
+			word <<= 8;
+			word |= bitc[p];
+		}
+	} else {
+		for (p = 3; p >= 0; p--) {
+			word <<= 8;
+			word |= bitc[p];
+		}
+	}
+
+	return word;
+}
+
+static u32 check_header(const void *buf)
+{
+	u32 i, pattern;
+	int swap = SWAP_NO;
+	u32 *test = (u32 *)buf;
+
+	debug("%s: Let's check bitstream header\n", __func__);
+
+	/* Checking that passing bin is not a bitstream */
+	for (i = 0; i < ARRAY_SIZE(bin_format); i++) {
+		pattern = load_word(&test[i], swap);
+
+		/*
+		 * Bitstreams in binary format are swapped
+		 * compare to regular bistream.
+		 * Do not swap dummy word but if swap is done assume
+		 * that parsing buffer is binary format
+		 */
+		if ((__swab32(pattern) != DUMMY_WORD) &&
+		    (__swab32(pattern) == bin_format[i])) {
+			swap = SWAP_DONE;
+			debug("%s: data swapped - let's swap\n", __func__);
+		}
+
+		debug("%s: %d/%px: pattern %x/%x bin_format\n", __func__, i,
+		      &test[i], pattern, bin_format[i]);
+	}
+	debug("%s: Found bitstream header at %px %s swapinng\n", __func__,
+	      buf, swap == SWAP_NO ? "without" : "with");
+
+	return swap;
+}
+
+static void *check_data(u8 *buf, size_t bsize, u32 *swap)
+{
+	u32 word, p = 0; /* possition */
+
+	/* Because buf doesn't need to be aligned let's read it by chars */
+	for (p = 0; p < bsize; p++) {
+		word = load_word(&buf[p], SWAP_NO);
+		debug("%s: word %x %x/%px\n", __func__, word, p, &buf[p]);
+
+		/* Find the first bitstream dummy word */
+		if (word == DUMMY_WORD) {
+			debug("%s: Found dummy word at position %x/%px\n",
+			      __func__, p, &buf[p]);
+			*swap = check_header(&buf[p]);
+			if (*swap) {
+				/* FIXME add full bitstream checking here */
+				return &buf[p];
+			}
+		}
+		/* Loop can be huge - support CTRL + C */
+		if (ctrlc())
+			return NULL;
+	}
+	return NULL;
+}
+
+static ulong zynqmp_align_dma_buffer(u32 *buf, u32 len, u32 swap)
+{
+	u32 *new_buf;
+	u32 i;
+
+	if ((ulong)buf != ALIGN((ulong)buf, ARCH_DMA_MINALIGN)) {
+		new_buf = (u32 *)ALIGN((ulong)buf, ARCH_DMA_MINALIGN);
+
+		/*
+		 * This might be dangerous but permits to flash if
+		 * ARCH_DMA_MINALIGN is greater than header size
+		 */
+		if (new_buf > (u32 *)buf) {
+			debug("%s: Aligned buffer is after buffer start\n",
+			      __func__);
+			new_buf -= ARCH_DMA_MINALIGN;
+		}
+		printf("%s: Align buffer at %px to %px(swap %d)\n", __func__,
+		       buf, new_buf, swap);
+
+		for (i = 0; i < (len/4); i++)
+			new_buf[i] = load_word(&buf[i], swap);
+
+		buf = new_buf;
+	} else if (swap != SWAP_DONE) {
+		/* For bitstream which are aligned */
+		u32 *new_buf = (u32 *)buf;
+
+		printf("%s: Bitstream is not swapped(%d) - swap it\n", __func__,
+		       swap);
+
+		for (i = 0; i < (len/4); i++)
+			new_buf[i] = load_word(&buf[i], swap);
+	}
+
+	return (ulong)buf;
+}
+
+static int zynqmp_validate_bitstream(xilinx_desc *desc, const void *buf,
+				   size_t bsize, u32 blocksize, u32 *swap)
+{
+	ulong *buf_start;
+	ulong diff;
+
+	buf_start = check_data((u8 *)buf, blocksize, swap);
+
+	if (!buf_start)
+		return FPGA_FAIL;
+
+	/* Check if data is postpone from start */
+	diff = (ulong)buf_start - (ulong)buf;
+	if (diff) {
+		printf("%s: Bitstream is not validated yet (diff %lx)\n",
+		       __func__, diff);
+		return FPGA_FAIL;
+	}
+
+	if ((ulong)buf < SZ_1M) {
+		printf("%s: Bitstream has to be placed up to 1MB (%px)\n",
+		       __func__, buf);
+		return FPGA_FAIL;
+	}
+
+	return 0;
+}
+
+static int invoke_smc(ulong id, ulong reg0, ulong reg1, ulong reg2)
+{
+	struct pt_regs regs;
+	regs.regs[0] = id;
+	regs.regs[1] = reg0;
+	regs.regs[2] = reg1;
+	regs.regs[3] = reg2;
+
+	smc_call(&regs);
+
+	return regs.regs[0];
+}
+
+static int zynqmp_load(xilinx_desc *desc, const void *buf, size_t bsize,
+		     bitstream_type bstype)
+{
+	u32 swap;
+	ulong bin_buf, flags;
+	int ret;
+
+	if (zynqmp_validate_bitstream(desc, buf, bsize, bsize, &swap))
+		return FPGA_FAIL;
+
+	bin_buf = zynqmp_align_dma_buffer((u32 *)buf, bsize, swap);
+
+	debug("%s called!\n", __func__);
+	flush_dcache_range(bin_buf, bin_buf + bsize);
+
+	if (bsize % 4)
+		bsize = bsize / 4 + 1;
+	else
+		bsize = bsize / 4;
+
+	flags = (u32)bsize | ((u64)bstype << 32);
+
+	ret = invoke_smc(ZYNQMP_SIP_SVC_PM_FPGA_LOAD, bin_buf, flags, 0);
+	if (ret)
+		debug("PL FPGA LOAD fail\n");
+
+	return ret;
+}
+
+struct xilinx_fpga_op zynqmp_op = {
+	.load = zynqmp_load,
+};
diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c
index afc674d..074f86c 100644
--- a/drivers/mmc/dw_mmc.c
+++ b/drivers/mmc/dw_mmc.c
@@ -120,9 +120,9 @@
 
 		if (host->fifo_mode && size) {
 			len = 0;
-			if (data->flags == MMC_DATA_READ) {
-				if ((dwmci_readl(host, DWMCI_RINTSTS) &
-				     DWMCI_INTMSK_RXDR)) {
+			if (data->flags == MMC_DATA_READ &&
+			    (mask & DWMCI_INTMSK_RXDR)) {
+				while (size) {
 					len = dwmci_readl(host, DWMCI_STATUS);
 					len = (len >> DWMCI_FIFO_SHIFT) &
 						    DWMCI_FIFO_MASK;
@@ -130,12 +130,13 @@
 					for (i = 0; i < len; i++)
 						*buf++ =
 						dwmci_readl(host, DWMCI_DATA);
-					dwmci_writel(host, DWMCI_RINTSTS,
-						     DWMCI_INTMSK_RXDR);
+					size = size > len ? (size - len) : 0;
 				}
-			} else {
-				if ((dwmci_readl(host, DWMCI_RINTSTS) &
-				     DWMCI_INTMSK_TXDR)) {
+				dwmci_writel(host, DWMCI_RINTSTS,
+					     DWMCI_INTMSK_RXDR);
+			} else if (data->flags == MMC_DATA_WRITE &&
+				   (mask & DWMCI_INTMSK_TXDR)) {
+				while (size) {
 					len = dwmci_readl(host, DWMCI_STATUS);
 					len = fifo_depth - ((len >>
 						   DWMCI_FIFO_SHIFT) &
@@ -144,11 +145,11 @@
 					for (i = 0; i < len; i++)
 						dwmci_writel(host, DWMCI_DATA,
 							     *buf++);
-					dwmci_writel(host, DWMCI_RINTSTS,
-						     DWMCI_INTMSK_TXDR);
+					size = size > len ? (size - len) : 0;
 				}
+				dwmci_writel(host, DWMCI_RINTSTS,
+					     DWMCI_INTMSK_TXDR);
 			}
-			size = size > len ? (size - len) : 0;
 		}
 
 		/* Data arrived correctly. */
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 43ea0bb..0312da9 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -21,6 +21,14 @@
 #include <div64.h>
 #include "mmc_private.h"
 
+static const unsigned int sd_au_size[] = {
+	0,		SZ_16K / 512,		SZ_32K / 512,
+	SZ_64K / 512,	SZ_128K / 512,		SZ_256K / 512,
+	SZ_512K / 512,	SZ_1M / 512,		SZ_2M / 512,
+	SZ_4M / 512,	SZ_8M / 512,		(SZ_8M + SZ_4M) / 512,
+	SZ_16M / 512,	(SZ_16M + SZ_8M) / 512,	SZ_32M / 512,	SZ_64M / 512,
+};
+
 #ifndef CONFIG_DM_MMC_OPS
 __weak int board_mmc_getwp(struct mmc *mmc)
 {
@@ -945,6 +953,62 @@
 	return 0;
 }
 
+static int sd_read_ssr(struct mmc *mmc)
+{
+	int err, i;
+	struct mmc_cmd cmd;
+	ALLOC_CACHE_ALIGN_BUFFER(uint, ssr, 16);
+	struct mmc_data data;
+	int timeout = 3;
+	unsigned int au, eo, et, es;
+
+	cmd.cmdidx = MMC_CMD_APP_CMD;
+	cmd.resp_type = MMC_RSP_R1;
+	cmd.cmdarg = mmc->rca << 16;
+
+	err = mmc_send_cmd(mmc, &cmd, NULL);
+	if (err)
+		return err;
+
+	cmd.cmdidx = SD_CMD_APP_SD_STATUS;
+	cmd.resp_type = MMC_RSP_R1;
+	cmd.cmdarg = 0;
+
+retry_ssr:
+	data.dest = (char *)ssr;
+	data.blocksize = 64;
+	data.blocks = 1;
+	data.flags = MMC_DATA_READ;
+
+	err = mmc_send_cmd(mmc, &cmd, &data);
+	if (err) {
+		if (timeout--)
+			goto retry_ssr;
+
+		return err;
+	}
+
+	for (i = 0; i < 16; i++)
+		ssr[i] = be32_to_cpu(ssr[i]);
+
+	au = (ssr[2] >> 12) & 0xF;
+	if ((au <= 9) || (mmc->version == SD_VERSION_3)) {
+		mmc->ssr.au = sd_au_size[au];
+		es = (ssr[3] >> 24) & 0xFF;
+		es |= (ssr[2] & 0xFF) << 8;
+		et = (ssr[3] >> 18) & 0x3F;
+		if (es && et) {
+			eo = (ssr[3] >> 16) & 0x3;
+			mmc->ssr.erase_timeout = (et * 1000) / es;
+			mmc->ssr.erase_offset = eo * 1000;
+		}
+	} else {
+		debug("Invalid Allocation Unit Size.\n");
+	}
+
+	return 0;
+}
+
 /* frequency bases */
 /* divided by 10 to be nice to platforms without floating point */
 static const int fbase[] = {
@@ -1350,6 +1414,10 @@
 			mmc_set_bus_width(mmc, 4);
 		}
 
+		err = sd_read_ssr(mmc);
+		if (err)
+			return err;
+
 		if (mmc->card_caps & MMC_MODE_HS)
 			mmc->tran_speed = 50000000;
 		else
diff --git a/drivers/mmc/mmc_write.c b/drivers/mmc/mmc_write.c
index 0f8b5c7..2289640 100644
--- a/drivers/mmc/mmc_write.c
+++ b/drivers/mmc/mmc_write.c
@@ -100,8 +100,13 @@
 		       & ~(mmc->erase_grp_size - 1)) - 1);
 
 	while (blk < blkcnt) {
-		blk_r = ((blkcnt - blk) > mmc->erase_grp_size) ?
-			mmc->erase_grp_size : (blkcnt - blk);
+		if (IS_SD(mmc) && mmc->ssr.au) {
+			blk_r = ((blkcnt - blk) > mmc->ssr.au) ?
+				mmc->ssr.au : (blkcnt - blk);
+		} else {
+			blk_r = ((blkcnt - blk) > mmc->erase_grp_size) ?
+				mmc->erase_grp_size : (blkcnt - blk);
+		}
 		err = mmc_erase_t(mmc, start + blk, blk_r);
 		if (err)
 			break;
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index 7ddb549..b2bf5a0 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -121,13 +121,10 @@
  * for card ready state.
  * Every time when card is busy after timeout then (last) timeout value will be
  * increased twice but only if it doesn't exceed global defined maximum.
- * Each function call will use last timeout value. Max timeout can be redefined
- * in board config file.
+ * Each function call will use last timeout value.
  */
-#ifndef CONFIG_SDHCI_CMD_MAX_TIMEOUT
-#define CONFIG_SDHCI_CMD_MAX_TIMEOUT		3200
-#endif
-#define CONFIG_SDHCI_CMD_DEFAULT_TIMEOUT	100
+#define SDHCI_CMD_MAX_TIMEOUT			3200
+#define SDHCI_CMD_DEFAULT_TIMEOUT		100
 #define SDHCI_READ_STATUS_TIMEOUT		1000
 
 #ifdef CONFIG_DM_MMC_OPS
@@ -151,7 +148,7 @@
 	unsigned start = get_timer(0);
 
 	/* Timeout unit - ms */
-	static unsigned int cmd_timeout = CONFIG_SDHCI_CMD_DEFAULT_TIMEOUT;
+	static unsigned int cmd_timeout = SDHCI_CMD_DEFAULT_TIMEOUT;
 
 	sdhci_writel(host, SDHCI_INT_ALL_MASK, SDHCI_INT_STATUS);
 	mask = SDHCI_CMD_INHIBIT | SDHCI_DATA_INHIBIT;
@@ -164,7 +161,7 @@
 	while (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) {
 		if (time >= cmd_timeout) {
 			printf("%s: MMC: %d busy ", __func__, mmc_dev);
-			if (2 * cmd_timeout <= CONFIG_SDHCI_CMD_MAX_TIMEOUT) {
+			if (2 * cmd_timeout <= SDHCI_CMD_MAX_TIMEOUT) {
 				cmd_timeout += cmd_timeout;
 				printf("timeout increasing to: %u ms.\n",
 				       cmd_timeout);
@@ -297,7 +294,7 @@
 static int sdhci_set_clock(struct mmc *mmc, unsigned int clock)
 {
 	struct sdhci_host *host = mmc->priv;
-	unsigned int div, clk, timeout, reg;
+	unsigned int div, clk = 0, timeout, reg;
 
 	/* Wait max 20 ms */
 	timeout = 200;
@@ -321,14 +318,36 @@
 		return 0;
 
 	if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) {
-		/* Version 3.00 divisors must be a multiple of 2. */
-		if (mmc->cfg->f_max <= clock)
-			div = 1;
-		else {
-			for (div = 2; div < SDHCI_MAX_DIV_SPEC_300; div += 2) {
-				if ((mmc->cfg->f_max / div) <= clock)
+		/*
+		 * Check if the Host Controller supports Programmable Clock
+		 * Mode.
+		 */
+		if (host->clk_mul) {
+			for (div = 1; div <= 1024; div++) {
+				if ((mmc->cfg->f_max * host->clk_mul / div)
+					<= clock)
 					break;
 			}
+
+			/*
+			 * Set Programmable Clock Mode in the Clock
+			 * Control register.
+			 */
+			clk = SDHCI_PROG_CLOCK_MODE;
+			div--;
+		} else {
+			/* Version 3.00 divisors must be a multiple of 2. */
+			if (mmc->cfg->f_max <= clock) {
+				div = 1;
+			} else {
+				for (div = 2;
+				     div < SDHCI_MAX_DIV_SPEC_300;
+				     div += 2) {
+					if ((mmc->cfg->f_max / div) <= clock)
+						break;
+				}
+			}
+			div >>= 1;
 		}
 	} else {
 		/* Version 2.00 divisors must be a power of 2. */
@@ -336,13 +355,13 @@
 			if ((mmc->cfg->f_max / div) <= clock)
 				break;
 		}
+		div >>= 1;
 	}
-	div >>= 1;
 
 	if (host->set_clock)
 		host->set_clock(host->index, div);
 
-	clk = (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT;
+	clk |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT;
 	clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN)
 		<< SDHCI_DIVIDER_HI_SHIFT;
 	clk |= SDHCI_CLOCK_INT_EN;
@@ -451,6 +470,8 @@
 {
 	struct sdhci_host *host = mmc->priv;
 
+	sdhci_reset(host, SDHCI_RESET_ALL);
+
 	if ((host->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR) && !aligned_buffer) {
 		aligned_buffer = memalign(8, 512*1024);
 		if (!aligned_buffer) {
@@ -514,9 +535,17 @@
 int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host,
 		u32 max_clk, u32 min_clk)
 {
-	u32 caps;
+	u32 caps, caps_1;
 
 	caps = sdhci_readl(host, SDHCI_CAPABILITIES);
+
+#ifdef CONFIG_MMC_SDMA
+	if (!(caps & SDHCI_CAN_DO_SDMA)) {
+		printf("%s: Your controller doesn't support SDMA!!\n",
+		       __func__);
+		return -EINVAL;
+	}
+#endif
 	host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
 
 	cfg->name = host->name;
@@ -534,8 +563,11 @@
 				SDHCI_CLOCK_BASE_SHIFT;
 		cfg->f_max *= 1000000;
 	}
-	if (cfg->f_max == 0)
+	if (cfg->f_max == 0) {
+		printf("%s: Hardware doesn't specify base clock frequency\n",
+		       __func__);
 		return -EINVAL;
+	}
 	if (min_clk)
 		cfg->f_min = min_clk;
 	else {
@@ -552,6 +584,9 @@
 	if (caps & SDHCI_CAN_VDD_180)
 		cfg->voltages |= MMC_VDD_165_195;
 
+	if (host->quirks & SDHCI_QUIRK_BROKEN_VOLTAGE)
+		cfg->voltages |= host->voltages;
+
 	cfg->host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_4BIT;
 	if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) {
 		if (caps & SDHCI_CAN_DO_8BIT)
@@ -564,6 +599,14 @@
 
 	cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
 
+	/*
+	 * In case of Host Controller v3.00, find out whether clock
+	 * multiplier is supported.
+	 */
+	caps_1 = sdhci_readl(host, SDHCI_CAPABILITIES_1);
+	host->clk_mul = (caps_1 & SDHCI_CLOCK_MUL_MASK) >>
+			SDHCI_CLOCK_MUL_SHIFT;
+
 	return 0;
 }
 
@@ -575,27 +618,11 @@
 #else
 int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk)
 {
-#ifdef CONFIG_MMC_SDMA
-	unsigned int caps;
+	int ret;
 
-	caps = sdhci_readl(host, SDHCI_CAPABILITIES);
-	if (!(caps & SDHCI_CAN_DO_SDMA)) {
-		printf("%s: Your controller doesn't support SDMA!!\n",
-		       __func__);
-		return -1;
-	}
-#endif
-
-	if (sdhci_setup_cfg(&host->cfg, host, max_clk, min_clk)) {
-		printf("%s: Hardware doesn't specify base clock frequency\n",
-		       __func__);
-		return -EINVAL;
-	}
-
-	if (host->quirks & SDHCI_QUIRK_BROKEN_VOLTAGE)
-		host->cfg.voltages |= host->voltages;
-
-	sdhci_reset(host, SDHCI_RESET_ALL);
+	ret = sdhci_setup_cfg(&host->cfg, host, max_clk, min_clk);
+	if (ret)
+		return ret;
 
 	host->mmc = mmc_create(&host->cfg, host);
 	if (host->mmc == NULL) {
diff --git a/drivers/mtd/spi/sandbox.c b/drivers/mtd/spi/sandbox.c
index 53470b9..f59134f 100644
--- a/drivers/mtd/spi/sandbox.c
+++ b/drivers/mtd/spi/sandbox.c
@@ -292,10 +292,7 @@
 				sbsf->data->nr_sectors;
 		} else if (sbsf->cmd == CMD_ERASE_4K && (flags & SECT_4K)) {
 			sbsf->erase_size = 4 << 10;
-		} else if (sbsf->cmd == CMD_ERASE_32K && (flags & SECT_32K)) {
-			sbsf->erase_size = 32 << 10;
-		} else if (sbsf->cmd == CMD_ERASE_64K &&
-			   !(flags & (SECT_4K | SECT_32K))) {
+		} else if (sbsf->cmd == CMD_ERASE_64K && !(flags & SECT_4K)) {
 			sbsf->erase_size = 64 << 10;
 		} else {
 			debug(" cmd unknown: %#x\n", sbsf->cmd);
diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h
index da2bb7b..cde4cfb 100644
--- a/drivers/mtd/spi/sf_internal.h
+++ b/drivers/mtd/spi/sf_internal.h
@@ -20,34 +20,6 @@
 	SF_DUAL_PARALLEL_FLASH	= BIT(1),
 };
 
-/* Enum list - Full read commands */
-enum spi_read_cmds {
-	ARRAY_SLOW		= BIT(0),
-	ARRAY_FAST		= BIT(1),
-	DUAL_OUTPUT_FAST	= BIT(2),
-	QUAD_OUTPUT_FAST	= BIT(3),
-	DUAL_IO_FAST		= BIT(4),
-	QUAD_IO_FAST		= BIT(5),
-};
-
-/* Normal - Extended - Full command set */
-#define RD_NORM		(ARRAY_SLOW | ARRAY_FAST)
-#define RD_EXTN		(RD_NORM | DUAL_OUTPUT_FAST | DUAL_IO_FAST)
-#define RD_FULL		(RD_EXTN | QUAD_OUTPUT_FAST | QUAD_IO_FAST)
-
-/* sf param flags */
-enum {
-#ifndef CONFIG_SPI_FLASH_USE_4K_SECTORS
-	SECT_4K		= 0,
-#else
-	SECT_4K		= BIT(0),
-#endif
-	SECT_32K	= BIT(1),
-	E_FSR		= BIT(2),
-	SST_WR		= BIT(3),
-	WR_QPP		= BIT(4),
-};
-
 enum spi_nor_option_flags {
 	SNOR_F_SST_WR		= BIT(0),
 	SNOR_F_USE_FSR		= BIT(1),
@@ -67,7 +39,6 @@
 
 /* Erase commands */
 #define CMD_ERASE_4K			0x20
-#define CMD_ERASE_32K			0x52
 #define CMD_ERASE_CHIP			0xc7
 #define CMD_ERASE_64K			0xd8
 
@@ -141,7 +112,6 @@
  * @sector_size:	Isn't necessarily a sector size from vendor,
  *			the size listed here is what works with CMD_ERASE_64K
  * @nr_sectors:		No.of sectors on this device
- * @e_rd_cmd:		Enum list for read commands
  * @flags:		Important param, for flash specific behaviour
  */
 struct spi_flash_params {
@@ -150,8 +120,17 @@
 	u16 ext_jedec;
 	u32 sector_size;
 	u32 nr_sectors;
-	u8 e_rd_cmd;
+
 	u16 flags;
+#define SECT_4K			BIT(0)
+#define E_FSR			BIT(1)
+#define SST_WR			BIT(2)
+#define WR_QPP			BIT(3)
+#define RD_QUAD			BIT(4)
+#define RD_DUAL			BIT(5)
+#define RD_QUADIO		BIT(6)
+#define RD_DUALIO		BIT(7)
+#define RD_FULL			(RD_QUAD | RD_DUAL | RD_QUADIO | RD_DUALIO)
 };
 
 extern const struct spi_flash_params spi_flash_params_table[];
diff --git a/drivers/mtd/spi/sf_params.c b/drivers/mtd/spi/sf_params.c
index 70ca236..5b50114 100644
--- a/drivers/mtd/spi/sf_params.c
+++ b/drivers/mtd/spi/sf_params.c
@@ -15,122 +15,122 @@
 /* SPI/QSPI flash device params structure */
 const struct spi_flash_params spi_flash_params_table[] = {
 #ifdef CONFIG_SPI_FLASH_ATMEL		/* ATMEL */
-	{"AT45DB011D",	   0x1f2200, 0x0,	64 * 1024,     4, RD_NORM,		    SECT_4K},
-	{"AT45DB021D",	   0x1f2300, 0x0,	64 * 1024,     8, RD_NORM,		    SECT_4K},
-	{"AT45DB041D",	   0x1f2400, 0x0,	64 * 1024,     8, RD_NORM,		    SECT_4K},
-	{"AT45DB081D",	   0x1f2500, 0x0,	64 * 1024,    16, RD_NORM,		    SECT_4K},
-	{"AT45DB161D",	   0x1f2600, 0x0,	64 * 1024,    32, RD_NORM,		    SECT_4K},
-	{"AT45DB321D",	   0x1f2700, 0x0,	64 * 1024,    64, RD_NORM,		    SECT_4K},
-	{"AT45DB641D",	   0x1f2800, 0x0,	64 * 1024,   128, RD_NORM,		    SECT_4K},
-	{"AT25DF321A",     0x1f4701, 0x0,	64 * 1024,    64, RD_NORM,		    SECT_4K},
-	{"AT25DF321",      0x1f4700, 0x0,	64 * 1024,    64, RD_NORM,		    SECT_4K},
-	{"AT26DF081A",     0x1f4501, 0x0,	64 * 1024,    16, RD_NORM,		    SECT_4K},
+	{"AT45DB011D",	   0x1f2200, 0x0,	64 * 1024,     4, SECT_4K},
+	{"AT45DB021D",	   0x1f2300, 0x0,	64 * 1024,     8, SECT_4K},
+	{"AT45DB041D",	   0x1f2400, 0x0,	64 * 1024,     8, SECT_4K},
+	{"AT45DB081D",	   0x1f2500, 0x0,	64 * 1024,    16, SECT_4K},
+	{"AT45DB161D",	   0x1f2600, 0x0,	64 * 1024,    32, SECT_4K},
+	{"AT45DB321D",	   0x1f2700, 0x0,	64 * 1024,    64, SECT_4K},
+	{"AT45DB641D",	   0x1f2800, 0x0,	64 * 1024,   128, SECT_4K},
+	{"AT25DF321A",     0x1f4701, 0x0,	64 * 1024,    64, SECT_4K},
+	{"AT25DF321",      0x1f4700, 0x0,	64 * 1024,    64, SECT_4K},
+	{"AT26DF081A",     0x1f4501, 0x0,	64 * 1024,    16, SECT_4K},
 #endif
 #ifdef CONFIG_SPI_FLASH_EON		/* EON */
-	{"EN25Q32B",	   0x1c3016, 0x0,	64 * 1024,    64, RD_NORM,			  0},
-	{"EN25Q64",	   0x1c3017, 0x0,	64 * 1024,   128, RD_NORM,		    SECT_4K},
-	{"EN25Q128B",	   0x1c3018, 0x0,       64 * 1024,   256, RD_NORM,			  0},
-	{"EN25S64",	   0x1c3817, 0x0,	64 * 1024,   128, RD_NORM,			  0},
+	{"EN25Q32B",	   0x1c3016, 0x0,	64 * 1024,    64, 0},
+	{"EN25Q64",	   0x1c3017, 0x0,	64 * 1024,   128, SECT_4K},
+	{"EN25Q128B",	   0x1c3018, 0x0,       64 * 1024,   256, 0},
+	{"EN25S64",	   0x1c3817, 0x0,	64 * 1024,   128, 0},
 #endif
 #ifdef CONFIG_SPI_FLASH_GIGADEVICE	/* GIGADEVICE */
-	{"GD25Q64B",	   0xc84017, 0x0,	64 * 1024,   128, RD_NORM,		    SECT_4K},
-	{"GD25LQ32",	   0xc86016, 0x0,	64 * 1024,    64, RD_NORM,		    SECT_4K},
+	{"GD25Q64B",	   0xc84017, 0x0,	64 * 1024,   128, SECT_4K},
+	{"GD25LQ32",	   0xc86016, 0x0,	64 * 1024,    64, SECT_4K},
 #endif
 #ifdef CONFIG_SPI_FLASH_ISSI		/* ISSI */
-	{"IS25LP032",	   0x9d6016, 0x0,	64 * 1024,    64, RD_NORM,			  0},
-	{"IS25LP064",	   0x9d6017, 0x0,	64 * 1024,   128, RD_NORM,			  0},
-	{"IS25LP128",	   0x9d6018, 0x0,	64 * 1024,   256, RD_NORM,			  0},
+	{"IS25LP032",	   0x9d6016, 0x0,	64 * 1024,    64, 0},
+	{"IS25LP064",	   0x9d6017, 0x0,	64 * 1024,   128, 0},
+	{"IS25LP128",	   0x9d6018, 0x0,	64 * 1024,   256, 0},
 #endif
 #ifdef CONFIG_SPI_FLASH_MACRONIX	/* MACRONIX */
-	{"MX25L2006E",	   0xc22012, 0x0,	64 * 1024,     4, RD_NORM,			  0},
-	{"MX25L4005",	   0xc22013, 0x0,	64 * 1024,     8, RD_NORM,			  0},
-	{"MX25L8005",	   0xc22014, 0x0,	64 * 1024,    16, RD_NORM,			  0},
-	{"MX25L1605D",	   0xc22015, 0x0,	64 * 1024,    32, RD_NORM,			  0},
-	{"MX25L3205D",	   0xc22016, 0x0,	64 * 1024,    64, RD_NORM,			  0},
-	{"MX25L6405D",	   0xc22017, 0x0,	64 * 1024,   128, RD_NORM,			  0},
-	{"MX25L12805",	   0xc22018, 0x0,	64 * 1024,   256, RD_FULL,		     WR_QPP},
-	{"MX25L25635F",	   0xc22019, 0x0,	64 * 1024,   512, RD_FULL,		     WR_QPP},
-	{"MX25L51235F",	   0xc2201a, 0x0,	64 * 1024,  1024, RD_FULL,		     WR_QPP},
-	{"MX25L12855E",	   0xc22618, 0x0,	64 * 1024,   256, RD_FULL,		     WR_QPP},
+	{"MX25L2006E",	   0xc22012, 0x0,	64 * 1024,     4, 0},
+	{"MX25L4005",	   0xc22013, 0x0,	64 * 1024,     8, 0},
+	{"MX25L8005",	   0xc22014, 0x0,	64 * 1024,    16, 0},
+	{"MX25L1605D",	   0xc22015, 0x0,	64 * 1024,    32, 0},
+	{"MX25L3205D",	   0xc22016, 0x0,	64 * 1024,    64, 0},
+	{"MX25L6405D",	   0xc22017, 0x0,	64 * 1024,   128, 0},
+	{"MX25L12805",	   0xc22018, 0x0,	64 * 1024,   256, RD_FULL | WR_QPP},
+	{"MX25L25635F",	   0xc22019, 0x0,	64 * 1024,   512, RD_FULL | WR_QPP},
+	{"MX25L51235F",	   0xc2201a, 0x0,	64 * 1024,  1024, RD_FULL | WR_QPP},
+	{"MX25L12855E",	   0xc22618, 0x0,	64 * 1024,   256, RD_FULL | WR_QPP},
 #endif
 #ifdef CONFIG_SPI_FLASH_SPANSION	/* SPANSION */
-	{"S25FL008A",	   0x010213, 0x0,	64 * 1024,    16, RD_NORM,			  0},
-	{"S25FL016A",	   0x010214, 0x0,	64 * 1024,    32, RD_NORM,			  0},
-	{"S25FL032A",	   0x010215, 0x0,	64 * 1024,    64, RD_NORM,			  0},
-	{"S25FL064A",	   0x010216, 0x0,	64 * 1024,   128, RD_NORM,			  0},
-	{"S25FL116K",	   0x014015, 0x0,	64 * 1024,   128, RD_NORM,			  0},
-	{"S25FL164K",	   0x014017, 0x0140,	64 * 1024,   128, RD_NORM,			  0},
-	{"S25FL128P_256K", 0x012018, 0x0300,   256 * 1024,    64, RD_FULL,		     WR_QPP},
-	{"S25FL128P_64K",  0x012018, 0x0301,    64 * 1024,   256, RD_FULL,		     WR_QPP},
-	{"S25FL032P",	   0x010215, 0x4d00,    64 * 1024,    64, RD_FULL,		     WR_QPP},
-	{"S25FL064P",	   0x010216, 0x4d00,    64 * 1024,   128, RD_FULL,		     WR_QPP},
-	{"S25FL128S_256K", 0x012018, 0x4d00,   256 * 1024,    64, RD_FULL,		     WR_QPP},
-	{"S25FL128S_64K",  0x012018, 0x4d01,    64 * 1024,   256, RD_FULL,		     WR_QPP},
-	{"S25FL256S_256K", 0x010219, 0x4d00,   256 * 1024,   128, RD_FULL,		     WR_QPP},
-	{"S25FL256S_64K",  0x010219, 0x4d01,	64 * 1024,   512, RD_FULL,		     WR_QPP},
-	{"S25FS512S",      0x010220, 0x4D00,   128 * 1024,   512, RD_FULL,                   WR_QPP},
-	{"S25FL512S_256K", 0x010220, 0x4d00,   256 * 1024,   256, RD_FULL,		     WR_QPP},
-	{"S25FL512S_64K",  0x010220, 0x4d01,    64 * 1024,  1024, RD_FULL,		     WR_QPP},
-	{"S25FL512S_512K", 0x010220, 0x4f00,   256 * 1024,   256, RD_FULL,		     WR_QPP},
+	{"S25FL008A",	   0x010213, 0x0,	64 * 1024,    16, 0},
+	{"S25FL016A",	   0x010214, 0x0,	64 * 1024,    32, 0},
+	{"S25FL032A",	   0x010215, 0x0,	64 * 1024,    64, 0},
+	{"S25FL064A",	   0x010216, 0x0,	64 * 1024,   128, 0},
+	{"S25FL116K",	   0x014015, 0x0,	64 * 1024,   128, 0},
+	{"S25FL164K",	   0x014017, 0x0140,	64 * 1024,   128, 0},
+	{"S25FL128P_256K", 0x012018, 0x0300,   256 * 1024,    64, RD_FULL | WR_QPP},
+	{"S25FL128P_64K",  0x012018, 0x0301,    64 * 1024,   256, RD_FULL | WR_QPP},
+	{"S25FL032P",	   0x010215, 0x4d00,    64 * 1024,    64, RD_FULL | WR_QPP},
+	{"S25FL064P",	   0x010216, 0x4d00,    64 * 1024,   128, RD_FULL | WR_QPP},
+	{"S25FL128S_256K", 0x012018, 0x4d00,   256 * 1024,    64, RD_FULL | WR_QPP},
+	{"S25FL128S_64K",  0x012018, 0x4d01,    64 * 1024,   256, RD_FULL | WR_QPP},
+	{"S25FL256S_256K", 0x010219, 0x4d00,   256 * 1024,   128, RD_FULL | WR_QPP},
+	{"S25FL256S_64K",  0x010219, 0x4d01,	64 * 1024,   512, RD_FULL | WR_QPP},
+	{"S25FS512S",      0x010220, 0x4D00,   128 * 1024,   512, RD_FULL | WR_QPP},
+	{"S25FL512S_256K", 0x010220, 0x4d00,   256 * 1024,   256, RD_FULL | WR_QPP},
+	{"S25FL512S_64K",  0x010220, 0x4d01,    64 * 1024,  1024, RD_FULL | WR_QPP},
+	{"S25FL512S_512K", 0x010220, 0x4f00,   256 * 1024,   256, RD_FULL | WR_QPP},
 #endif
 #ifdef CONFIG_SPI_FLASH_STMICRO		/* STMICRO */
-	{"M25P10",	   0x202011, 0x0,	32 * 1024,     4, RD_NORM,			  0},
-	{"M25P20",	   0x202012, 0x0,       64 * 1024,     4, RD_NORM,			  0},
-	{"M25P40",	   0x202013, 0x0,       64 * 1024,     8, RD_NORM,			  0},
-	{"M25P80",	   0x202014, 0x0,       64 * 1024,    16, RD_NORM,			  0},
-	{"M25P16",	   0x202015, 0x0,       64 * 1024,    32, RD_NORM,			  0},
-	{"M25PE16",	   0x208015, 0x1000,    64 * 1024,    32, RD_NORM,			  0},
-	{"M25PX16",	   0x207115, 0x1000,    64 * 1024,    32, RD_EXTN,			  0},
-	{"M25P32",	   0x202016, 0x0,       64 * 1024,    64, RD_NORM,			  0},
-	{"M25P64",	   0x202017, 0x0,       64 * 1024,   128, RD_NORM,			  0},
-	{"M25P128",	   0x202018, 0x0,      256 * 1024,    64, RD_NORM,			  0},
-	{"M25PX64",	   0x207117, 0x0,       64 * 1024,   128, RD_NORM,		    SECT_4K},
-	{"N25Q016A",       0x20bb15, 0x0,	64 * 1024,    32, RD_NORM,                  SECT_4K},
-	{"N25Q32",	   0x20ba16, 0x0,       64 * 1024,    64, RD_FULL,	   WR_QPP | SECT_4K},
-	{"N25Q32A",	   0x20bb16, 0x0,       64 * 1024,    64, RD_FULL,	   WR_QPP | SECT_4K},
-	{"N25Q64",	   0x20ba17, 0x0,       64 * 1024,   128, RD_FULL,	   WR_QPP | SECT_4K},
-	{"N25Q64A",	   0x20bb17, 0x0,       64 * 1024,   128, RD_FULL,	   WR_QPP | SECT_4K},
-	{"N25Q128",	   0x20ba18, 0x0,       64 * 1024,   256, RD_FULL,		     WR_QPP},
-	{"N25Q128A",	   0x20bb18, 0x0,       64 * 1024,   256, RD_FULL,		     WR_QPP},
-	{"N25Q256",	   0x20ba19, 0x0,       64 * 1024,   512, RD_FULL,	   WR_QPP | SECT_4K},
-	{"N25Q256A",	   0x20bb19, 0x0,       64 * 1024,   512, RD_FULL,	   WR_QPP | SECT_4K},
-	{"N25Q512",	   0x20ba20, 0x0,       64 * 1024,  1024, RD_FULL, WR_QPP | E_FSR | SECT_4K},
-	{"N25Q512A",	   0x20bb20, 0x0,       64 * 1024,  1024, RD_FULL, WR_QPP | E_FSR | SECT_4K},
-	{"N25Q1024",	   0x20ba21, 0x0,       64 * 1024,  2048, RD_FULL, WR_QPP | E_FSR | SECT_4K},
-	{"N25Q1024A",	   0x20bb21, 0x0,       64 * 1024,  2048, RD_FULL, WR_QPP | E_FSR | SECT_4K},
+	{"M25P10",	   0x202011, 0x0,	32 * 1024,     4, 0},
+	{"M25P20",	   0x202012, 0x0,       64 * 1024,     4, 0},
+	{"M25P40",	   0x202013, 0x0,       64 * 1024,     8, 0},
+	{"M25P80",	   0x202014, 0x0,       64 * 1024,    16, 0},
+	{"M25P16",	   0x202015, 0x0,       64 * 1024,    32, 0},
+	{"M25PE16",	   0x208015, 0x1000,    64 * 1024,    32, 0},
+	{"M25PX16",	   0x207115, 0x1000,    64 * 1024,    32, RD_QUAD | RD_DUAL},
+	{"M25P32",	   0x202016, 0x0,       64 * 1024,    64, 0},
+	{"M25P64",	   0x202017, 0x0,       64 * 1024,   128, 0},
+	{"M25P128",	   0x202018, 0x0,      256 * 1024,    64, 0},
+	{"M25PX64",	   0x207117, 0x0,       64 * 1024,   128, SECT_4K},
+	{"N25Q016A",       0x20bb15, 0x0,	64 * 1024,    32, SECT_4K},
+	{"N25Q32",	   0x20ba16, 0x0,       64 * 1024,    64, RD_FULL | WR_QPP | SECT_4K},
+	{"N25Q32A",	   0x20bb16, 0x0,       64 * 1024,    64, RD_FULL | WR_QPP | SECT_4K},
+	{"N25Q64",	   0x20ba17, 0x0,       64 * 1024,   128, RD_FULL | WR_QPP | SECT_4K},
+	{"N25Q64A",	   0x20bb17, 0x0,       64 * 1024,   128, RD_FULL | WR_QPP | SECT_4K},
+	{"N25Q128",	   0x20ba18, 0x0,       64 * 1024,   256, RD_FULL | WR_QPP},
+	{"N25Q128A",	   0x20bb18, 0x0,       64 * 1024,   256, RD_FULL | WR_QPP},
+	{"N25Q256",	   0x20ba19, 0x0,       64 * 1024,   512, RD_FULL | WR_QPP | SECT_4K},
+	{"N25Q256A",	   0x20bb19, 0x0,       64 * 1024,   512, RD_FULL | WR_QPP | SECT_4K},
+	{"N25Q512",	   0x20ba20, 0x0,       64 * 1024,  1024, RD_FULL | WR_QPP | E_FSR | SECT_4K},
+	{"N25Q512A",	   0x20bb20, 0x0,       64 * 1024,  1024, RD_FULL | WR_QPP | E_FSR | SECT_4K},
+	{"N25Q1024",	   0x20ba21, 0x0,       64 * 1024,  2048, RD_FULL | WR_QPP | E_FSR | SECT_4K},
+	{"N25Q1024A",	   0x20bb21, 0x0,       64 * 1024,  2048, RD_FULL | WR_QPP | E_FSR | SECT_4K},
 #endif
 #ifdef CONFIG_SPI_FLASH_SST		/* SST */
-	{"SST25VF040B",	   0xbf258d, 0x0,	64 * 1024,     8, RD_NORM,          SECT_4K | SST_WR},
-	{"SST25VF080B",	   0xbf258e, 0x0,	64 * 1024,    16, RD_NORM,	    SECT_4K | SST_WR},
-	{"SST25VF016B",	   0xbf2541, 0x0,	64 * 1024,    32, RD_NORM,	    SECT_4K | SST_WR},
-	{"SST25VF032B",	   0xbf254a, 0x0,	64 * 1024,    64, RD_NORM,	    SECT_4K | SST_WR},
-	{"SST25VF064C",	   0xbf254b, 0x0,	64 * 1024,   128, RD_NORM,		     SECT_4K},
-	{"SST25WF512",	   0xbf2501, 0x0,	64 * 1024,     1, RD_NORM,	    SECT_4K | SST_WR},
-	{"SST25WF010",	   0xbf2502, 0x0,	64 * 1024,     2, RD_NORM,          SECT_4K | SST_WR},
-	{"SST25WF020",	   0xbf2503, 0x0,	64 * 1024,     4, RD_NORM,	    SECT_4K | SST_WR},
-	{"SST25WF040",	   0xbf2504, 0x0,	64 * 1024,     8, RD_NORM,	    SECT_4K | SST_WR},
-	{"SST25WF040B",	   0x621613, 0x0,	64 * 1024,     8, RD_NORM,		     SECT_4K},
-	{"SST25WF080",	   0xbf2505, 0x0,	64 * 1024,    16, RD_NORM,	    SECT_4K | SST_WR},
+	{"SST25VF040B",	   0xbf258d, 0x0,	64 * 1024,     8, SECT_4K | SST_WR},
+	{"SST25VF080B",	   0xbf258e, 0x0,	64 * 1024,    16, SECT_4K | SST_WR},
+	{"SST25VF016B",	   0xbf2541, 0x0,	64 * 1024,    32, SECT_4K | SST_WR},
+	{"SST25VF032B",	   0xbf254a, 0x0,	64 * 1024,    64, SECT_4K | SST_WR},
+	{"SST25VF064C",	   0xbf254b, 0x0,	64 * 1024,   128, SECT_4K},
+	{"SST25WF512",	   0xbf2501, 0x0,	64 * 1024,     1, SECT_4K | SST_WR},
+	{"SST25WF010",	   0xbf2502, 0x0,	64 * 1024,     2, SECT_4K | SST_WR},
+	{"SST25WF020",	   0xbf2503, 0x0,	64 * 1024,     4, SECT_4K | SST_WR},
+	{"SST25WF040",	   0xbf2504, 0x0,	64 * 1024,     8, SECT_4K | SST_WR},
+	{"SST25WF040B",	   0x621613, 0x0,	64 * 1024,     8, SECT_4K},
+	{"SST25WF080",	   0xbf2505, 0x0,	64 * 1024,    16, SECT_4K | SST_WR},
 #endif
 #ifdef CONFIG_SPI_FLASH_WINBOND		/* WINBOND */
-	{"W25P80",	   0xef2014, 0x0,	64 * 1024,    16, RD_NORM,		           0},
-	{"W25P16",	   0xef2015, 0x0,	64 * 1024,    32, RD_NORM,		           0},
-	{"W25P32",	   0xef2016, 0x0,	64 * 1024,    64, RD_NORM,		           0},
-	{"W25X40",	   0xef3013, 0x0,	64 * 1024,     8, RD_NORM,		     SECT_4K},
-	{"W25X16",	   0xef3015, 0x0,	64 * 1024,    32, RD_NORM,		     SECT_4K},
-	{"W25X32",	   0xef3016, 0x0,	64 * 1024,    64, RD_NORM,		     SECT_4K},
-	{"W25X64",	   0xef3017, 0x0,	64 * 1024,   128, RD_NORM,		     SECT_4K},
-	{"W25Q80BL",	   0xef4014, 0x0,	64 * 1024,    16, RD_FULL,	    WR_QPP | SECT_4K},
-	{"W25Q16CL",	   0xef4015, 0x0,	64 * 1024,    32, RD_FULL,	    WR_QPP | SECT_4K},
-	{"W25Q32BV",	   0xef4016, 0x0,	64 * 1024,    64, RD_FULL,	    WR_QPP | SECT_4K},
-	{"W25Q64CV",	   0xef4017, 0x0,	64 * 1024,   128, RD_FULL,	    WR_QPP | SECT_4K},
-	{"W25Q128BV",	   0xef4018, 0x0,	64 * 1024,   256, RD_FULL,	    WR_QPP | SECT_4K},
-	{"W25Q256",	   0xef4019, 0x0,	64 * 1024,   512, RD_FULL,	    WR_QPP | SECT_4K},
-	{"W25Q80BW",	   0xef5014, 0x0,	64 * 1024,    16, RD_FULL,	    WR_QPP | SECT_4K},
-	{"W25Q16DW",	   0xef6015, 0x0,	64 * 1024,    32, RD_FULL,	    WR_QPP | SECT_4K},
-	{"W25Q32DW",	   0xef6016, 0x0,	64 * 1024,    64, RD_FULL,	    WR_QPP | SECT_4K},
-	{"W25Q64DW",	   0xef6017, 0x0,	64 * 1024,   128, RD_FULL,	    WR_QPP | SECT_4K},
-	{"W25Q128FW",	   0xef6018, 0x0,	64 * 1024,   256, RD_FULL,	    WR_QPP | SECT_4K},
+	{"W25P80",	   0xef2014, 0x0,	64 * 1024,    16, 0},
+	{"W25P16",	   0xef2015, 0x0,	64 * 1024,    32, 0},
+	{"W25P32",	   0xef2016, 0x0,	64 * 1024,    64, 0},
+	{"W25X40",	   0xef3013, 0x0,	64 * 1024,     8, SECT_4K},
+	{"W25X16",	   0xef3015, 0x0,	64 * 1024,    32, SECT_4K},
+	{"W25X32",	   0xef3016, 0x0,	64 * 1024,    64, SECT_4K},
+	{"W25X64",	   0xef3017, 0x0,	64 * 1024,   128, SECT_4K},
+	{"W25Q80BL",	   0xef4014, 0x0,	64 * 1024,    16, RD_FULL | WR_QPP | SECT_4K},
+	{"W25Q16CL",	   0xef4015, 0x0,	64 * 1024,    32, RD_FULL | WR_QPP | SECT_4K},
+	{"W25Q32BV",	   0xef4016, 0x0,	64 * 1024,    64, RD_FULL | WR_QPP | SECT_4K},
+	{"W25Q64CV",	   0xef4017, 0x0,	64 * 1024,   128, RD_FULL | WR_QPP | SECT_4K},
+	{"W25Q128BV",	   0xef4018, 0x0,	64 * 1024,   256, RD_FULL | WR_QPP | SECT_4K},
+	{"W25Q256",	   0xef4019, 0x0,	64 * 1024,   512, RD_FULL | WR_QPP | SECT_4K},
+	{"W25Q80BW",	   0xef5014, 0x0,	64 * 1024,    16, RD_FULL | WR_QPP | SECT_4K},
+	{"W25Q16DW",	   0xef6015, 0x0,	64 * 1024,    32, RD_FULL | WR_QPP | SECT_4K},
+	{"W25Q32DW",	   0xef6016, 0x0,	64 * 1024,    64, RD_FULL | WR_QPP | SECT_4K},
+	{"W25Q64DW",	   0xef6017, 0x0,	64 * 1024,   128, RD_FULL | WR_QPP | SECT_4K},
+	{"W25Q128FW",	   0xef6018, 0x0,	64 * 1024,   256, RD_FULL | WR_QPP | SECT_4K},
 #endif
 	{},	/* Empty entry to terminate the list */
 	/*
diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index 64d4e0f..7f6e9ae 100644
--- a/drivers/mtd/spi/spi_flash.c
+++ b/drivers/mtd/spi/spi_flash.c
@@ -1013,15 +1013,8 @@
 	struct spi_slave *spi = flash->spi;
 	const struct spi_flash_params *params;
 	u16 jedec, ext_jedec;
-	u8 cmd, idcode[5];
+	u8 idcode[5];
 	int ret;
-	static u8 spi_read_cmds_array[] = {
-		CMD_READ_ARRAY_SLOW,
-		CMD_READ_ARRAY_FAST,
-		CMD_READ_DUAL_OUTPUT_FAST,
-		CMD_READ_QUAD_OUTPUT_FAST,
-		CMD_READ_DUAL_IO_FAST,
-		CMD_READ_QUAD_IO_FAST };
 
 	/* Read the ID codes */
 	ret = spi_flash_cmd(spi, CMD_READ_ID, idcode, sizeof(idcode));
@@ -1162,14 +1155,14 @@
 		flash->size <<= 1;
 #endif
 
+#ifdef CONFIG_SPI_FLASH_USE_4K_SECTORS
 	/* Compute erase sector and command */
 	if (params->flags & SECT_4K) {
 		flash->erase_cmd = CMD_ERASE_4K;
 		flash->erase_size = 4096 << flash->shift;
-	} else if (params->flags & SECT_32K) {
-		flash->erase_cmd = CMD_ERASE_32K;
-		flash->erase_size = 32768 << flash->shift;
-	} else {
+	} else
+#endif
+	{
 		flash->erase_cmd = CMD_ERASE_64K;
 		flash->erase_size = flash->sector_size;
 	}
@@ -1177,17 +1170,16 @@
 	/* Now erase size becomes valid sector size */
 	flash->sector_size = flash->erase_size;
 
-	/* Look for the fastest read cmd */
-	cmd = fls(params->e_rd_cmd & spi->mode_rx);
-	if (cmd) {
-		cmd = spi_read_cmds_array[cmd - 1];
-		flash->read_cmd = cmd;
-	} else {
-		/* Go for default supported read cmd */
-		flash->read_cmd = CMD_READ_ARRAY_FAST;
-	}
+	/* Look for read commands */
+	flash->read_cmd = CMD_READ_ARRAY_FAST;
+	if (spi->mode & SPI_RX_SLOW)
+		flash->read_cmd = CMD_READ_ARRAY_SLOW;
+	else if (spi->mode & SPI_RX_QUAD && params->flags & RD_QUAD)
+		flash->read_cmd = CMD_READ_QUAD_OUTPUT_FAST;
+	else if (spi->mode & SPI_RX_DUAL && params->flags & RD_DUAL)
+		flash->read_cmd = CMD_READ_DUAL_OUTPUT_FAST;
 
-	/* Not require to look for fastest only two write cmds yet */
+	/* Look for write commands */
 	if (params->flags & WR_QPP && spi->mode & SPI_TX_QUAD)
 		flash->write_cmd = CMD_QUAD_PAGE_PROGRAM;
 	else
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index be3ed73..302c005 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -175,7 +175,7 @@
 	  This MAC is present in Xilinx Microblaze, Zynq and ZynqMP SoCs.
 
 config XILINX_EMACLITE
-	depends on DM_ETH && (MICROBLAZE || ARCH_ZYNQ || ARCH_ZYNQMP)
+	depends on DM_ETH && (MICROBLAZE || ARCH_ZYNQ || ARCH_ZYNQMP || MIPS)
 	select PHYLIB
 	select MII
 	bool "Xilinx Ethernetlite"
diff --git a/drivers/net/pch_gbe.c b/drivers/net/pch_gbe.c
index 137818b..d40fff0 100644
--- a/drivers/net/pch_gbe.c
+++ b/drivers/net/pch_gbe.c
@@ -118,14 +118,14 @@
 	memset(rx_desc, 0, sizeof(struct pch_gbe_rx_desc) * PCH_GBE_DESC_NUM);
 	for (i = 0; i < PCH_GBE_DESC_NUM; i++)
 		rx_desc->buffer_addr = dm_pci_phys_to_mem(priv->dev,
-			(u32)(priv->rx_buff[i]));
+			(ulong)(priv->rx_buff[i]));
 
-	writel(dm_pci_phys_to_mem(priv->dev, (u32)rx_desc),
+	writel(dm_pci_phys_to_mem(priv->dev, (ulong)rx_desc),
 	       &mac_regs->rx_dsc_base);
 	writel(sizeof(struct pch_gbe_rx_desc) * (PCH_GBE_DESC_NUM - 1),
 	       &mac_regs->rx_dsc_size);
 
-	writel(dm_pci_phys_to_mem(priv->dev, (u32)(rx_desc + 1)),
+	writel(dm_pci_phys_to_mem(priv->dev, (ulong)(rx_desc + 1)),
 	       &mac_regs->rx_dsc_sw_p);
 }
 
@@ -137,11 +137,11 @@
 
 	memset(tx_desc, 0, sizeof(struct pch_gbe_tx_desc) * PCH_GBE_DESC_NUM);
 
-	writel(dm_pci_phys_to_mem(priv->dev, (u32)tx_desc),
+	writel(dm_pci_phys_to_mem(priv->dev, (ulong)tx_desc),
 	       &mac_regs->tx_dsc_base);
 	writel(sizeof(struct pch_gbe_tx_desc) * (PCH_GBE_DESC_NUM - 1),
 	       &mac_regs->tx_dsc_size);
-	writel(dm_pci_phys_to_mem(priv->dev, (u32)(tx_desc + 1)),
+	writel(dm_pci_phys_to_mem(priv->dev, (ulong)(tx_desc + 1)),
 	       &mac_regs->tx_dsc_sw_p);
 }
 
@@ -251,7 +251,7 @@
 	if (length < 64)
 		frame_ctrl |= PCH_GBE_TXD_CTRL_APAD;
 
-	tx_desc->buffer_addr = dm_pci_phys_to_mem(priv->dev, (u32)packet);
+	tx_desc->buffer_addr = dm_pci_phys_to_mem(priv->dev, (ulong)packet);
 	tx_desc->length = length;
 	tx_desc->tx_words_eob = length + 3;
 	tx_desc->tx_frame_ctrl = frame_ctrl;
@@ -262,7 +262,7 @@
 	if (++priv->tx_idx >= PCH_GBE_DESC_NUM)
 		priv->tx_idx = 0;
 
-	writel(dm_pci_phys_to_mem(priv->dev, (u32)(tx_head + priv->tx_idx)),
+	writel(dm_pci_phys_to_mem(priv->dev, (ulong)(tx_head + priv->tx_idx)),
 	       &mac_regs->tx_dsc_sw_p);
 
 	start = get_timer(0);
@@ -283,7 +283,7 @@
 	struct pch_gbe_priv *priv = dev_get_priv(dev);
 	struct pch_gbe_regs *mac_regs = priv->mac_regs;
 	struct pch_gbe_rx_desc *rx_desc;
-	u32 hw_desc, buffer_addr, length;
+	ulong hw_desc, buffer_addr, length;
 
 	rx_desc = &priv->rx_desc[priv->rx_idx];
 
@@ -291,7 +291,7 @@
 	hw_desc = readl(&mac_regs->rx_dsc_hw_p_hld);
 
 	/* Just return if not receiving any packet */
-	if ((u32)rx_desc == hw_desc)
+	if ((ulong)rx_desc == hw_desc)
 		return -EAGAIN;
 
 	buffer_addr = dm_pci_mem_to_phys(priv->dev, rx_desc->buffer_addr);
@@ -315,7 +315,7 @@
 	if (++rx_swp >= PCH_GBE_DESC_NUM)
 		rx_swp = 0;
 
-	writel(dm_pci_phys_to_mem(priv->dev, (u32)(rx_head + rx_swp)),
+	writel(dm_pci_phys_to_mem(priv->dev, (ulong)(rx_head + rx_swp)),
 	       &mac_regs->rx_dsc_sw_p);
 
 	return 0;
@@ -421,7 +421,7 @@
 {
 	struct pch_gbe_priv *priv;
 	struct eth_pdata *plat = dev_get_platdata(dev);
-	u32 iobase;
+	void *iobase;
 
 	/*
 	 * The priv structure contains the descriptors and frame buffers which
@@ -432,11 +432,9 @@
 
 	priv->dev = dev;
 
-	dm_pci_read_config32(dev, PCI_BASE_ADDRESS_1, &iobase);
-	iobase &= PCI_BASE_ADDRESS_MEM_MASK;
-	iobase = dm_pci_mem_to_phys(dev, iobase);
+	iobase = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_1, PCI_REGION_MEM);
 
-	plat->iobase = iobase;
+	plat->iobase = (ulong)iobase;
 	priv->mac_regs = (struct pch_gbe_regs *)iobase;
 
 	/* Read MAC address from SROM and initialize dev->enetaddr with it */
diff --git a/drivers/net/xilinx_emaclite.c b/drivers/net/xilinx_emaclite.c
index 7b85aa0..d86e7a3 100644
--- a/drivers/net/xilinx_emaclite.c
+++ b/drivers/net/xilinx_emaclite.c
@@ -19,6 +19,7 @@
 #include <fdtdec.h>
 #include <asm-generic/errno.h>
 #include <linux/kernel.h>
+#include <asm/io.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -154,7 +155,7 @@
 	unsigned long start = get_timer(0);
 
 	while (1) {
-		val = readl(reg);
+		val = __raw_readl(reg);
 
 		if (!set)
 			val = ~val;
@@ -193,16 +194,17 @@
 	if (mdio_wait(regs))
 		return 1;
 
-	u32 ctrl_reg = in_be32(&regs->mdioctrl);
-	out_be32(&regs->mdioaddr, XEL_MDIOADDR_OP_MASK |
-		 ((phyaddress << XEL_MDIOADDR_PHYADR_SHIFT) | registernum));
-	out_be32(&regs->mdioctrl, ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK);
+	u32 ctrl_reg = __raw_readl(&regs->mdioctrl);
+	__raw_writel(XEL_MDIOADDR_OP_MASK
+		| ((phyaddress << XEL_MDIOADDR_PHYADR_SHIFT)
+		| registernum), &regs->mdioaddr);
+	__raw_writel(ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK, &regs->mdioctrl);
 
 	if (mdio_wait(regs))
 		return 1;
 
 	/* Read data */
-	*data = in_be32(&regs->mdiord);
+	*data = __raw_readl(&regs->mdiord);
 	return 0;
 }
 
@@ -220,11 +222,12 @@
 	 * Data register. Finally, set the Status bit in the MDIO Control
 	 * register to start a MDIO write transaction.
 	 */
-	u32 ctrl_reg = in_be32(&regs->mdioctrl);
-	out_be32(&regs->mdioaddr, ~XEL_MDIOADDR_OP_MASK &
-		 ((phyaddress << XEL_MDIOADDR_PHYADR_SHIFT) | registernum));
-	out_be32(&regs->mdiowr, data);
-	out_be32(&regs->mdioctrl, ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK);
+	u32 ctrl_reg = __raw_readl(&regs->mdioctrl);
+	__raw_writel(~XEL_MDIOADDR_OP_MASK
+		& ((phyaddress << XEL_MDIOADDR_PHYADR_SHIFT)
+		| registernum), &regs->mdioaddr);
+	__raw_writel(data, &regs->mdiowr);
+	__raw_writel(ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK, &regs->mdioctrl);
 
 	if (mdio_wait(regs))
 		return 1;
@@ -327,27 +330,27 @@
  * TX - TX_PING & TX_PONG initialization
  */
 	/* Restart PING TX */
-	out_be32(&regs->tx_ping_tsr, 0);
+	__raw_writel(0, &regs->tx_ping_tsr);
 	/* Copy MAC address */
 	xemaclite_alignedwrite(pdata->enetaddr, &regs->tx_ping,
 			       ENET_ADDR_LENGTH);
 	/* Set the length */
-	out_be32(&regs->tx_ping_tplr, ENET_ADDR_LENGTH);
+	__raw_writel(ENET_ADDR_LENGTH, &regs->tx_ping_tplr);
 	/* Update the MAC address in the EMAC Lite */
-	out_be32(&regs->tx_ping_tsr, XEL_TSR_PROG_MAC_ADDR);
+	__raw_writel(XEL_TSR_PROG_MAC_ADDR, &regs->tx_ping_tsr);
 	/* Wait for EMAC Lite to finish with the MAC address update */
-	while ((in_be32 (&regs->tx_ping_tsr) &
+	while ((__raw_readl(&regs->tx_ping_tsr) &
 		XEL_TSR_PROG_MAC_ADDR) != 0)
 		;
 
 	if (emaclite->txpp) {
 		/* The same operation with PONG TX */
-		out_be32(&regs->tx_pong_tsr, 0);
+		__raw_writel(0, &regs->tx_pong_tsr);
 		xemaclite_alignedwrite(pdata->enetaddr, &regs->tx_pong,
 				       ENET_ADDR_LENGTH);
-		out_be32(&regs->tx_pong_tplr, ENET_ADDR_LENGTH);
-		out_be32(&regs->tx_pong_tsr, XEL_TSR_PROG_MAC_ADDR);
-		while ((in_be32(&regs->tx_pong_tsr) &
+		__raw_writel(ENET_ADDR_LENGTH, &regs->tx_pong_tplr);
+		__raw_writel(XEL_TSR_PROG_MAC_ADDR, &regs->tx_pong_tsr);
+		while ((__raw_readl(&regs->tx_pong_tsr) &
 		       XEL_TSR_PROG_MAC_ADDR) != 0)
 			;
 	}
@@ -356,13 +359,13 @@
  * RX - RX_PING & RX_PONG initialization
  */
 	/* Write out the value to flush the RX buffer */
-	out_be32(&regs->rx_ping_rsr, XEL_RSR_RECV_IE_MASK);
+	__raw_writel(XEL_RSR_RECV_IE_MASK, &regs->rx_ping_rsr);
 
 	if (emaclite->rxpp)
-		out_be32(&regs->rx_pong_rsr, XEL_RSR_RECV_IE_MASK);
+		__raw_writel(XEL_RSR_RECV_IE_MASK, &regs->rx_pong_rsr);
 
-	out_be32(&regs->mdioctrl, XEL_MDIOCTRL_MDIOEN_MASK);
-	if (in_be32(&regs->mdioctrl) & XEL_MDIOCTRL_MDIOEN_MASK)
+	__raw_writel(XEL_MDIOCTRL_MDIOEN_MASK, &regs->mdioctrl);
+	if (__raw_readl(&regs->mdioctrl) & XEL_MDIOCTRL_MDIOEN_MASK)
 		if (!setup_phy(dev))
 			return -1;
 
@@ -379,9 +382,9 @@
 	 * Read the other buffer register
 	 * and determine if the other buffer is available
 	 */
-	tmp = ~in_be32(&regs->tx_ping_tsr);
+	tmp = ~__raw_readl(&regs->tx_ping_tsr);
 	if (emaclite->txpp)
-		tmp |= ~in_be32(&regs->tx_pong_tsr);
+		tmp |= ~__raw_readl(&regs->tx_pong_tsr);
 
 	return !(tmp & XEL_TSR_XMIT_BUSY_MASK);
 }
@@ -405,40 +408,42 @@
 	if (!maxtry) {
 		printf("Error: Timeout waiting for ethernet TX buffer\n");
 		/* Restart PING TX */
-		out_be32(&regs->tx_ping_tsr, 0);
+		__raw_writel(0, &regs->tx_ping_tsr);
 		if (emaclite->txpp) {
-			out_be32(&regs->tx_pong_tsr, 0);
+			__raw_writel(0, &regs->tx_pong_tsr);
 		}
 		return -1;
 	}
 
 	/* Determine if the expected buffer address is empty */
-	reg = in_be32(&regs->tx_ping_tsr);
+	reg = __raw_readl(&regs->tx_ping_tsr);
 	if ((reg & XEL_TSR_XMIT_BUSY_MASK) == 0) {
 		debug("Send packet from tx_ping buffer\n");
 		/* Write the frame to the buffer */
 		xemaclite_alignedwrite(ptr, &regs->tx_ping, len);
-		out_be32(&regs->tx_ping_tplr, len &
-			(XEL_TPLR_LENGTH_MASK_HI | XEL_TPLR_LENGTH_MASK_LO));
-		reg = in_be32(&regs->tx_ping_tsr);
+		__raw_writel(len
+			& (XEL_TPLR_LENGTH_MASK_HI | XEL_TPLR_LENGTH_MASK_LO),
+		       &regs->tx_ping_tplr);
+		reg = __raw_readl(&regs->tx_ping_tsr);
 		reg |= XEL_TSR_XMIT_BUSY_MASK;
-		out_be32(&regs->tx_ping_tsr, reg);
+		__raw_writel(reg, &regs->tx_ping_tsr);
 		return 0;
 	}
 
 	if (emaclite->txpp) {
 		/* Determine if the expected buffer address is empty */
-		reg = in_be32(&regs->tx_pong_tsr);
+		reg = __raw_readl(&regs->tx_pong_tsr);
 		if ((reg & XEL_TSR_XMIT_BUSY_MASK) == 0) {
 			debug("Send packet from tx_pong buffer\n");
 			/* Write the frame to the buffer */
 			xemaclite_alignedwrite(ptr, &regs->tx_pong, len);
-			out_be32(&regs->tx_pong_tplr, len &
+			__raw_writel(len &
 				 (XEL_TPLR_LENGTH_MASK_HI |
-				  XEL_TPLR_LENGTH_MASK_LO));
-			reg = in_be32(&regs->tx_pong_tsr);
+				  XEL_TPLR_LENGTH_MASK_LO),
+				  &regs->tx_pong_tplr);
+			reg = __raw_readl(&regs->tx_pong_tsr);
 			reg |= XEL_TSR_XMIT_BUSY_MASK;
-			out_be32(&regs->tx_pong_tsr, reg);
+			__raw_writel(reg, &regs->tx_pong_tsr);
 			return 0;
 		}
 	}
@@ -458,7 +463,7 @@
 
 try_again:
 	if (!emaclite->use_rx_pong_buffer_next) {
-		reg = in_be32(&regs->rx_ping_rsr);
+		reg = __raw_readl(&regs->rx_ping_rsr);
 		debug("Testing data at rx_ping\n");
 		if ((reg & XEL_RSR_RECV_DONE_MASK) == XEL_RSR_RECV_DONE_MASK) {
 			debug("Data found in rx_ping buffer\n");
@@ -478,7 +483,7 @@
 			goto try_again;
 		}
 	} else {
-		reg = in_be32(&regs->rx_pong_rsr);
+		reg = __raw_readl(&regs->rx_pong_rsr);
 		debug("Testing data at rx_pong\n");
 		if ((reg & XEL_RSR_RECV_DONE_MASK) == XEL_RSR_RECV_DONE_MASK) {
 			debug("Data found in rx_pong buffer\n");
@@ -525,9 +530,9 @@
 				      length - first_read);
 
 	/* Acknowledge the frame */
-	reg = in_be32(ack);
+	reg = __raw_readl(ack);
 	reg &= ~XEL_RSR_RECV_DONE_MASK;
-	out_be32(ack, reg);
+	__raw_writel(reg, ack);
 
 	debug("Packet receive from 0x%p, length %dB\n", addr, length);
 	*packetp = etherrxbuff;
@@ -595,7 +600,8 @@
 	int offset = 0;
 
 	pdata->iobase = (phys_addr_t)dev_get_addr(dev);
-	emaclite->regs = (struct emaclite_regs *)pdata->iobase;
+	emaclite->regs = (struct emaclite_regs *)ioremap_nocache(pdata->iobase,
+								 0x10000);
 
 	emaclite->phyaddr = -1;
 
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 669e37b..9a7c187 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -39,4 +39,11 @@
 	  with a total of 5 lanes. Some boards require this for Ethernet
 	  support to work (e.g. beaver, jetson-tk1).
 
+config PCI_XILINX
+	bool "Xilinx AXI Bridge for PCI Express"
+	depends on DM_PCI
+	help
+	  Enable support for the Xilinx AXI bridge for PCI express, an IP block
+	  which can be used on some generations of Xilinx FPGAs.
+
 endmenu
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index f8be9bf..9583e91 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -31,3 +31,4 @@
 obj-$(CONFIG_TSI108_PCI) += tsi108_pci.o
 obj-$(CONFIG_WINBOND_83C553) += w83c553f.o
 obj-$(CONFIG_PCIE_LAYERSCAPE) += pcie_layerscape.o
+obj-$(CONFIG_PCI_XILINX) += pcie_xilinx.o
diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c
index 342b78c..3b00e6a 100644
--- a/drivers/pci/pci-uclass.c
+++ b/drivers/pci/pci-uclass.c
@@ -837,7 +837,7 @@
 	hose = bus->uclass_priv;
 
 	/* For bridges, use the top-level PCI controller */
-	if (device_get_uclass_id(bus->parent) == UCLASS_ROOT) {
+	if (!device_is_on_pci_bus(bus)) {
 		hose->ctlr = bus;
 		ret = decode_regions(hose, gd->fdt_blob, bus->parent->of_offset,
 				bus->of_offset);
diff --git a/drivers/pci/pcie_xilinx.c b/drivers/pci/pcie_xilinx.c
new file mode 100644
index 0000000..5216001
--- /dev/null
+++ b/drivers/pci/pcie_xilinx.c
@@ -0,0 +1,220 @@
+/*
+ * Xilinx AXI Bridge for PCI Express Driver
+ *
+ * Copyright (C) 2016 Imagination Technologies
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <pci.h>
+
+#include <asm/io.h>
+
+/**
+ * struct xilinx_pcie - Xilinx PCIe controller state
+ * @hose: The parent classes PCI controller state
+ * @cfg_base: The base address of memory mapped configuration space
+ */
+struct xilinx_pcie {
+	struct pci_controller hose;
+	void *cfg_base;
+};
+
+/* Register definitions */
+#define XILINX_PCIE_REG_PSCR		0x144
+#define XILINX_PCIE_REG_PSCR_LNKUP	BIT(11)
+
+/**
+ * pcie_xilinx_link_up() - Check whether the PCIe link is up
+ * @pcie: Pointer to the PCI controller state
+ *
+ * Checks whether the PCIe link for the given device is up or down.
+ *
+ * Return: true if the link is up, else false
+ */
+static bool pcie_xilinx_link_up(struct xilinx_pcie *pcie)
+{
+	uint32_t pscr = __raw_readl(pcie->cfg_base + XILINX_PCIE_REG_PSCR);
+
+	return pscr & XILINX_PCIE_REG_PSCR_LNKUP;
+}
+
+/**
+ * pcie_xilinx_config_address() - Calculate the address of a config access
+ * @pcie: Pointer to the PCI controller state
+ * @bdf: Identifies the PCIe device to access
+ * @offset: The offset into the device's configuration space
+ * @paddress: Pointer to the pointer to write the calculates address to
+ *
+ * Calculates the address that should be accessed to perform a PCIe
+ * configuration space access for a given device identified by the PCIe
+ * controller device @pcie and the bus, device & function numbers in @bdf. If
+ * access to the device is not valid then the function will return an error
+ * code. Otherwise the address to access will be written to the pointer pointed
+ * to by @paddress.
+ *
+ * Return: 0 on success, else -ENODEV
+ */
+static int pcie_xilinx_config_address(struct xilinx_pcie *pcie, pci_dev_t bdf,
+				      uint offset, void **paddress)
+{
+	unsigned int bus = PCI_BUS(bdf);
+	unsigned int dev = PCI_DEV(bdf);
+	unsigned int func = PCI_FUNC(bdf);
+	void *addr;
+
+	if ((bus > 0) && !pcie_xilinx_link_up(pcie))
+		return -ENODEV;
+
+	/*
+	 * Busses 0 (host-PCIe bridge) & 1 (its immediate child) are
+	 * limited to a single device each.
+	 */
+	if ((bus < 2) && (dev > 0))
+		return -ENODEV;
+
+	addr = pcie->cfg_base;
+	addr += bus << 20;
+	addr += dev << 15;
+	addr += func << 12;
+	addr += offset;
+	*paddress = addr;
+
+	return 0;
+}
+
+/**
+ * pcie_xilinx_read_config() - Read from configuration space
+ * @pcie: Pointer to the PCI controller state
+ * @bdf: Identifies the PCIe device to access
+ * @offset: The offset into the device's configuration space
+ * @valuep: A pointer at which to store the read value
+ * @size: Indicates the size of access to perform
+ *
+ * Read a value of size @size from offset @offset within the configuration
+ * space of the device identified by the bus, device & function numbers in @bdf
+ * on the PCI bus @bus.
+ *
+ * Return: 0 on success, else -ENODEV or -EINVAL
+ */
+static int pcie_xilinx_read_config(struct udevice *bus, pci_dev_t bdf,
+				   uint offset, ulong *valuep,
+				   enum pci_size_t size)
+{
+	struct xilinx_pcie *pcie = dev_get_priv(bus);
+	void *address;
+	int err;
+
+	err = pcie_xilinx_config_address(pcie, bdf, offset, &address);
+	if (err < 0) {
+		*valuep = pci_get_ff(size);
+		return 0;
+	}
+
+	switch (size) {
+	case PCI_SIZE_8:
+		*valuep = __raw_readb(address);
+		return 0;
+	case PCI_SIZE_16:
+		*valuep = __raw_readw(address);
+		return 0;
+	case PCI_SIZE_32:
+		*valuep = __raw_readl(address);
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
+/**
+ * pcie_xilinx_write_config() - Write to configuration space
+ * @pcie: Pointer to the PCI controller state
+ * @bdf: Identifies the PCIe device to access
+ * @offset: The offset into the device's configuration space
+ * @value: The value to write
+ * @size: Indicates the size of access to perform
+ *
+ * Write the value @value of size @size from offset @offset within the
+ * configuration space of the device identified by the bus, device & function
+ * numbers in @bdf on the PCI bus @bus.
+ *
+ * Return: 0 on success, else -ENODEV or -EINVAL
+ */
+static int pcie_xilinx_write_config(struct udevice *bus, pci_dev_t bdf,
+				    uint offset, ulong value,
+				    enum pci_size_t size)
+{
+	struct xilinx_pcie *pcie = dev_get_priv(bus);
+	void *address;
+	int err;
+
+	err = pcie_xilinx_config_address(pcie, bdf, offset, &address);
+	if (err < 0)
+		return 0;
+
+	switch (size) {
+	case PCI_SIZE_8:
+		__raw_writeb(value, address);
+		return 0;
+	case PCI_SIZE_16:
+		__raw_writew(value, address);
+		return 0;
+	case PCI_SIZE_32:
+		__raw_writel(value, address);
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
+/**
+ * pcie_xilinx_ofdata_to_platdata() - Translate from DT to device state
+ * @dev: A pointer to the device being operated on
+ *
+ * Translate relevant data from the device tree pertaining to device @dev into
+ * state that the driver will later make use of. This state is stored in the
+ * device's private data structure.
+ *
+ * Return: 0 on success, else -EINVAL
+ */
+static int pcie_xilinx_ofdata_to_platdata(struct udevice *dev)
+{
+	struct xilinx_pcie *pcie = dev_get_priv(dev);
+	struct fdt_resource reg_res;
+	DECLARE_GLOBAL_DATA_PTR;
+	int err;
+
+	err = fdt_get_resource(gd->fdt_blob, dev->of_offset, "reg",
+			       0, &reg_res);
+	if (err < 0) {
+		error("\"reg\" resource not found\n");
+		return err;
+	}
+
+	pcie->cfg_base = map_physmem(reg_res.start,
+				     fdt_resource_size(&reg_res),
+				     MAP_NOCACHE);
+
+	return 0;
+}
+
+static const struct dm_pci_ops pcie_xilinx_ops = {
+	.read_config	= pcie_xilinx_read_config,
+	.write_config	= pcie_xilinx_write_config,
+};
+
+static const struct udevice_id pcie_xilinx_ids[] = {
+	{ .compatible = "xlnx,axi-pcie-host-1.00.a" },
+	{ }
+};
+
+U_BOOT_DRIVER(pcie_xilinx) = {
+	.name			= "pcie_xilinx",
+	.id			= UCLASS_PCI,
+	.of_match		= pcie_xilinx_ids,
+	.ops			= &pcie_xilinx_ops,
+	.ofdata_to_platdata	= pcie_xilinx_ofdata_to_platdata,
+	.priv_auto_alloc_size	= sizeof(struct xilinx_pcie),
+};
diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c
index 88fca15..765499d 100644
--- a/drivers/serial/ns16550.c
+++ b/drivers/serial/ns16550.c
@@ -5,6 +5,7 @@
  */
 
 #include <common.h>
+#include <clk.h>
 #include <dm.h>
 #include <errno.h>
 #include <fdtdec.h>
@@ -12,6 +13,7 @@
 #include <serial.h>
 #include <watchdog.h>
 #include <linux/types.h>
+#include <linux/compiler.h>
 #include <asm/io.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -352,6 +354,8 @@
 {
 	struct ns16550_platdata *plat = dev->platdata;
 	fdt_addr_t addr;
+	__maybe_unused struct clk clk;
+	__maybe_unused int err;
 
 	/* try Processor Local Bus device first */
 	addr = dev_get_addr(dev);
@@ -397,9 +401,23 @@
 				     "reg-offset", 0);
 	plat->reg_shift = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
 					 "reg-shift", 0);
-	plat->clock = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
-				     "clock-frequency",
-				     CONFIG_SYS_NS16550_CLK);
+
+#ifdef CONFIG_CLK
+	err = clk_get_by_index(dev, 0, &clk);
+	if (!err) {
+		err = clk_get_rate(&clk);
+		if (!IS_ERR_VALUE(err))
+			plat->clock = err;
+	} else if (err != -ENODEV && err != -ENOSYS) {
+		debug("ns16550 failed to get clock\n");
+		return err;
+	}
+#endif
+
+	if (!plat->clock)
+		plat->clock = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+					     "clock-frequency",
+					     CONFIG_SYS_NS16550_CLK);
 	if (!plat->clock) {
 		debug("ns16550 clock not defined\n");
 		return -EINVAL;
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index aca385d..5da66a6 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -61,13 +61,6 @@
 	  this Freescale DSPI IP core. LS102xA and Colibri VF50/VF61 platforms
 	  use this driver.
 
-config FSL_QSPI
-	bool "Freescale QSPI driver"
-	help
-	  Enable the Freescale Quad-SPI (QSPI) driver. This driver can be
-	  used to access the SPI NOR flash on platforms embedding this
-	  Freescale IP core.
-
 config ICH_SPI
 	bool "Intel ICH SPI driver"
 	help
@@ -188,6 +181,13 @@
 	  access the SPI interface and SPI NOR flash on platforms embedding
 	  this Freescale eSPI IP core.
 
+config FSL_QSPI
+	bool "Freescale QSPI driver"
+	help
+	  Enable the Freescale Quad-SPI (QSPI) driver. This driver can be
+	  used to access the SPI NOR flash on platforms embedding this
+	  Freescale IP core.
+
 config TI_QSPI
 	bool "TI QSPI driver"
 	help
diff --git a/drivers/spi/cadence_qspi.c b/drivers/spi/cadence_qspi.c
index a5244ff..1d50f13 100644
--- a/drivers/spi/cadence_qspi.c
+++ b/drivers/spi/cadence_qspi.c
@@ -251,7 +251,7 @@
 		break;
 		case CQSPI_INDIRECT_READ:
 			err = cadence_qspi_apb_indirect_read_setup(plat,
-				priv->cmd_len, dm_plat->mode_rx, cmd_buf);
+				priv->cmd_len, dm_plat->mode, cmd_buf);
 			if (!err) {
 				err = cadence_qspi_apb_indirect_read_execute
 				(plat, data_bytes, din);
diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c
index 00b2fed..caf0103 100644
--- a/drivers/spi/ich.c
+++ b/drivers/spi/ich.c
@@ -649,10 +649,8 @@
 	 * ICH 7 SPI controller only supports array read command
 	 * and byte program command for SST flash
 	 */
-	if (plat->ich_version == ICHV_7) {
-		slave->mode_rx = SPI_RX_SLOW;
-		slave->mode = SPI_TX_BYTE;
-	}
+	if (plat->ich_version == ICHV_7)
+		slave->mode = SPI_RX_SLOW | SPI_TX_BYTE;
 
 	return 0;
 }
diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c
index 247abfa..d9c49e4 100644
--- a/drivers/spi/spi-uclass.c
+++ b/drivers/spi/spi-uclass.c
@@ -164,7 +164,6 @@
 
 	slave->max_hz = plat->max_hz;
 	slave->mode = plat->mode;
-	slave->mode_rx = plat->mode_rx;
 	slave->wordlen = SPI_DEFAULT_WORDLEN;
 
 	return 0;
@@ -381,7 +380,7 @@
 int spi_slave_ofdata_to_platdata(const void *blob, int node,
 				 struct dm_spi_slave_platdata *plat)
 {
-	int mode = 0, mode_rx = 0;
+	int mode = 0;
 	int value;
 
 	plat->cs = fdtdec_get_int(blob, node, "reg", -1);
@@ -413,24 +412,22 @@
 		break;
 	}
 
-	plat->mode = mode;
-
 	value = fdtdec_get_uint(blob, node, "spi-rx-bus-width", 1);
 	switch (value) {
 	case 1:
 		break;
 	case 2:
-		mode_rx |= SPI_RX_DUAL;
+		mode |= SPI_RX_DUAL;
 		break;
 	case 4:
-		mode_rx |= SPI_RX_QUAD;
+		mode |= SPI_RX_QUAD;
 		break;
 	default:
 		error("spi-rx-bus-width %d not supported\n", value);
 		break;
 	}
 
-	plat->mode_rx = mode_rx;
+	plat->mode = mode;
 
 	return 0;
 }
diff --git a/drivers/spi/ti_qspi.c b/drivers/spi/ti_qspi.c
index bb72cb0..52520df 100644
--- a/drivers/spi/ti_qspi.c
+++ b/drivers/spi/ti_qspi.c
@@ -23,6 +23,9 @@
 #define QSPI_TIMEOUT                    2000000
 #define QSPI_FCLK			192000000
 #define QSPI_DRA7XX_FCLK                76800000
+#define QSPI_WLEN_MAX_BITS		128
+#define QSPI_WLEN_MAX_BYTES		(QSPI_WLEN_MAX_BITS >> 3)
+#define QSPI_WLEN_MASK			QSPI_WLEN(QSPI_WLEN_MAX_BITS)
 /* clock control */
 #define QSPI_CLK_EN                     BIT(31)
 #define QSPI_CLK_DIV_MAX                0xffff
@@ -223,20 +226,34 @@
 		priv->cmd |= QSPI_3_PIN;
 	priv->cmd |= 0xfff;
 
-/* FIXME: This delay is required for successfull
- * completion of read/write/erase. Once its root
- * caused, it will be remove from the driver.
- */
-#ifdef CONFIG_AM43XX
-	udelay(100);
-#endif
-	while (words--) {
+	while (words) {
+		u8 xfer_len = 0;
+
 		if (txp) {
-			debug("tx cmd %08x dc %08x data %02x\n",
-			      priv->cmd | QSPI_WR_SNGL, priv->dc, *txp);
-			writel(*txp++, &priv->base->data);
-			writel(priv->cmd | QSPI_WR_SNGL,
-			       &priv->base->cmd);
+			u32 cmd = priv->cmd;
+
+			if (words >= QSPI_WLEN_MAX_BYTES) {
+				u32 *txbuf = (u32 *)txp;
+				u32 data;
+
+				data = cpu_to_be32(*txbuf++);
+				writel(data, &priv->base->data3);
+				data = cpu_to_be32(*txbuf++);
+				writel(data, &priv->base->data2);
+				data = cpu_to_be32(*txbuf++);
+				writel(data, &priv->base->data1);
+				data = cpu_to_be32(*txbuf++);
+				writel(data, &priv->base->data);
+				cmd &= ~QSPI_WLEN_MASK;
+				cmd |= QSPI_WLEN(QSPI_WLEN_MAX_BITS);
+				xfer_len = QSPI_WLEN_MAX_BYTES;
+			} else {
+				writeb(*txp, &priv->base->data);
+				xfer_len = 1;
+			}
+			debug("tx cmd %08x dc %08x\n",
+			      cmd | QSPI_WR_SNGL, priv->dc);
+			writel(cmd | QSPI_WR_SNGL, &priv->base->cmd);
 			status = readl(&priv->base->status);
 			timeout = QSPI_TIMEOUT;
 			while ((status & QSPI_WC_BUSY) != QSPI_XFER_DONE) {
@@ -246,6 +263,7 @@
 				}
 				status = readl(&priv->base->status);
 			}
+			txp += xfer_len;
 			debug("tx done, status %08x\n", status);
 		}
 		if (rxp) {
@@ -262,9 +280,11 @@
 				status = readl(&priv->base->status);
 			}
 			*rxp++ = readl(&priv->base->data);
+			xfer_len = 1;
 			debug("rx done, status %08x, read %02x\n",
 			      status, *(rxp-1));
 		}
+		words -= xfer_len;
 	}
 
 	/* Terminate frame */
@@ -336,7 +356,7 @@
 			QSPI_SETUP0_NUM_D_BYTES_8_BITS |
 			QSPI_SETUP0_READ_QUAD | QSPI_CMD_WRITE |
 			QSPI_NUM_DUMMY_BITS);
-	slave->mode_rx = SPI_RX_QUAD;
+	slave->mode |= SPI_RX_QUAD;
 #else
 	memval |= QSPI_CMD_READ | QSPI_SETUP0_NUM_A_BYTES |
 			QSPI_SETUP0_NUM_D_BYTES_NO_BITS |
@@ -422,7 +442,7 @@
 				      bool enable)
 {
 	u32 memval;
-	u32 mode = slave->mode_rx & (SPI_RX_QUAD | SPI_RX_DUAL);
+	u32 mode = slave->mode & (SPI_RX_QUAD | SPI_RX_DUAL);
 
 	if (!enable) {
 		writel(0, &priv->base->setup0);
@@ -436,7 +456,7 @@
 		memval |= QSPI_CMD_READ_QUAD;
 		memval |= QSPI_SETUP0_NUM_D_BYTES_8_BITS;
 		memval |= QSPI_SETUP0_READ_QUAD;
-		slave->mode_rx = SPI_RX_QUAD;
+		slave->mode |= SPI_RX_QUAD;
 		break;
 	case SPI_RX_DUAL:
 		memval |= QSPI_CMD_READ_DUAL;
diff --git a/drivers/spi/zynq_spi.c b/drivers/spi/zynq_spi.c
index 09ae1be..15ca271 100644
--- a/drivers/spi/zynq_spi.c
+++ b/drivers/spi/zynq_spi.c
@@ -92,7 +92,8 @@
 	u32 confr;
 
 	/* Disable SPI */
-	writel(~ZYNQ_SPI_ENR_SPI_EN_MASK, &regs->enr);
+	confr = ZYNQ_SPI_ENR_SPI_EN_MASK;
+	writel(~confr, &regs->enr);
 
 	/* Disable Interrupts */
 	writel(ZYNQ_SPI_IXR_ALL_MASK, &regs->idr);
@@ -173,8 +174,10 @@
 	struct udevice *bus = dev->parent;
 	struct zynq_spi_priv *priv = dev_get_priv(bus);
 	struct zynq_spi_regs *regs = priv->regs;
+	u32 confr;
 
-	writel(~ZYNQ_SPI_ENR_SPI_EN_MASK, &regs->enr);
+	confr = ZYNQ_SPI_ENR_SPI_EN_MASK;
+	writel(~confr, &regs->enr);
 
 	return 0;
 }
@@ -230,7 +233,7 @@
 
 		/* Read the data from RX FIFO */
 		status = readl(&regs->isr);
-		while (status & ZYNQ_SPI_IXR_RXNEMPTY_MASK) {
+		while ((status & ZYNQ_SPI_IXR_RXNEMPTY_MASK) && rx_len) {
 			buf = readl(&regs->rxdr);
 			if (rx_buf)
 				*rx_buf++ = buf;
diff --git a/include/clk.h b/include/clk.h
index dc18b03..7273127 100644
--- a/include/clk.h
+++ b/include/clk.h
@@ -10,6 +10,7 @@
 #define _CLK_H_
 
 #include <linux/types.h>
+#include <asm/errno.h>
 
 /**
  * A clock is a hardware signal that oscillates autonomously at a specific
@@ -59,7 +60,7 @@
 	unsigned long id;
 };
 
-#if CONFIG_IS_ENABLED(OF_CONTROL)
+#if CONFIG_IS_ENABLED(OF_CONTROL) && CONFIG_IS_ENABLED(CLK)
 struct phandle_2_cell;
 int clk_get_by_index_platdata(struct udevice *dev, int index,
 			      struct phandle_2_cell *cells, struct clk *clk);
@@ -97,19 +98,6 @@
  * @return 0 if OK, or a negative error code.
  */
 int clk_get_by_name(struct udevice *dev, const char *name, struct clk *clk);
-#else
-static inline int clk_get_by_index(struct udevice *dev, int index,
-				   struct clk *clk)
-{
-	return -ENOSYS;
-}
-
-static inline int clk_get_by_name(struct udevice *dev, const char *name,
-			   struct clk *clk)
-{
-	return -ENOSYS;
-}
-#endif
 
 /**
  * clk_request - Request a clock by provider-specific ID.
@@ -174,5 +162,17 @@
 int clk_disable(struct clk *clk);
 
 int soc_clk_dump(void);
+#else
+static inline int clk_get_by_index(struct udevice *dev, int index,
+				   struct clk *clk)
+{
+	return -ENOSYS;
+}
 
+static inline int clk_get_by_name(struct udevice *dev, const char *name,
+			   struct clk *clk)
+{
+	return -ENOSYS;
+}
+#endif
 #endif
diff --git a/include/configs/boston.h b/include/configs/boston.h
new file mode 100644
index 0000000..e958054
--- /dev/null
+++ b/include/configs/boston.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2016 Imagination Technologies
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef __CONFIGS_BOSTON_H__
+#define __CONFIGS_BOSTON_H__
+
+/*
+ * General board configuration
+ */
+#define CONFIG_DISPLAY_BOARDINFO
+
+/*
+ * CPU
+ */
+#define CONFIG_SYS_MIPS_TIMER_FREQ	30000000
+
+/*
+ * PCI
+ */
+#define CONFIG_PCI
+#define CONFIG_PCI_PNP
+#define CONFIG_CMD_PCI
+
+/*
+ * Memory map
+ */
+#ifdef CONFIG_64BIT
+# define CONFIG_SYS_SDRAM_BASE		0xffffffff80000000
+#else
+# define CONFIG_SYS_SDRAM_BASE		0x80000000
+#endif
+
+#define CONFIG_SYS_INIT_SP_OFFSET	0x400000
+
+#define CONFIG_SYS_MONITOR_BASE		CONFIG_SYS_TEXT_BASE
+
+#define CONFIG_SYS_LOAD_ADDR		(CONFIG_SYS_SDRAM_BASE + 0x100000)
+
+#define CONFIG_SYS_MEMTEST_START	(CONFIG_SYS_SDRAM_BASE + 0)
+#define CONFIG_SYS_MEMTEST_END		(CONFIG_SYS_SDRAM_BASE + 0x10000000)
+
+#define CONFIG_SYS_MALLOC_LEN		(256 * 1024)
+
+/*
+ * Console
+ */
+#define CONFIG_SYS_MAXARGS		16
+#define CONFIG_SYS_CBSIZE		256
+#define CONFIG_SYS_PBSIZE		(CONFIG_SYS_CBSIZE + \
+					 sizeof(CONFIG_SYS_PROMPT) + 16)
+#define CONFIG_SYS_LONGHELP
+#define CONFIG_BAUDRATE			115200
+
+/*
+ * Flash
+ */
+#define CONFIG_FLASH_CFI_DRIVER
+#define CONFIG_SYS_FLASH_CFI
+#define CONFIG_SYS_FLASH_PROTECTION
+#define CONFIG_SYS_FLASH_USE_BUFFER_WRITE
+#define CONFIG_SYS_MAX_FLASH_BANKS_DETECT	1
+#define CONFIG_SYS_MAX_FLASH_SECT		1024
+
+/*
+ * Environment
+ */
+#define CONFIG_ENV_IS_IN_FLASH
+#define CONFIG_ENV_SECT_SIZE		0x20000
+#define CONFIG_ENV_SIZE			CONFIG_ENV_SECT_SIZE
+#ifdef CONFIG_64BIT
+# define CONFIG_ENV_ADDR \
+	(0xffffffffb8000000 + (128 << 20) - CONFIG_ENV_SIZE)
+#else
+# define CONFIG_ENV_ADDR \
+	(0xb8000000 + (128 << 20) - CONFIG_ENV_SIZE)
+#endif
+
+#endif /* __CONFIGS_BOSTON_H__ */
diff --git a/include/configs/imgtec_xilfpga.h b/include/configs/imgtec_xilfpga.h
new file mode 100644
index 0000000..0a7fe60
--- /dev/null
+++ b/include/configs/imgtec_xilfpga.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2016, Imagination Technologies Ltd.
+ *
+ * Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ *
+ * Imagination Technologies Ltd. MIPSfpga
+ */
+
+#ifndef __XILFPGA_CONFIG_H
+#define __XILFPGA_CONFIG_H
+
+/* BootROM + MIG is pretty smart. DDR and Cache initialized */
+#define CONFIG_SKIP_LOWLEVEL_INIT
+
+/*--------------------------------------------
+ * CPU configuration
+ */
+/* CPU Timer rate */
+#define CONFIG_SYS_MIPS_TIMER_FREQ	50000000
+
+/* Cache Configuration */
+#define CONFIG_SYS_MIPS_CACHE_MODE	CONF_CM_CACHABLE_NONCOHERENT
+
+/*----------------------------------------------------------------------
+ * Memory Layout
+ */
+
+/* SDRAM Configuration (for final code, data, stack, heap) */
+#define CONFIG_SYS_SDRAM_BASE		0x80000000
+#define CONFIG_SYS_SDRAM_SIZE		0x08000000	/* 128 Mbytes */
+#define CONFIG_SYS_INIT_SP_ADDR		\
+	(CONFIG_SYS_SDRAM_BASE + CONFIG_SYS_SDRAM_SIZE - 0x1000)
+
+#define CONFIG_SYS_MALLOC_LEN		(256 << 10)
+#define CONFIG_SYS_MONITOR_BASE		CONFIG_SYS_TEXT_BASE
+#define CONFIG_SYS_LOAD_ADDR		0x80500000 /* default load address */
+
+/*----------------------------------------------------------------------
+ * Commands
+ */
+#define CONFIG_SYS_LONGHELP		/* undef to save memory */
+
+/*-------------------------------------------------
+ * FLASH configuration
+ */
+#define CONFIG_SYS_NO_FLASH
+
+/*------------------------------------------------------------
+ * Console Configuration
+ */
+#define CONFIG_SYS_CBSIZE		1024 /* Console I/O Buffer Size   */
+#define CONFIG_SYS_MAXARGS		16   /* max number of command args*/
+#define CONFIG_BAUDRATE			115200
+
+/* -------------------------------------------------
+ * Environment
+ */
+#define CONFIG_ENV_IS_NOWHERE	1
+#define CONFIG_ENV_SIZE		0x4000
+
+/* ---------------------------------------------------------------------
+ * Board boot configuration
+ */
+#define CONFIG_TIMESTAMP	/* Print image info with timestamp */
+
+#endif	/* __XILFPGA_CONFIG_H */
diff --git a/include/configs/mx6sxsabreauto.h b/include/configs/mx6sxsabreauto.h
index 274cb36..c30e3dd 100644
--- a/include/configs/mx6sxsabreauto.h
+++ b/include/configs/mx6sxsabreauto.h
@@ -173,7 +173,6 @@
 
 #define CONFIG_IMX_THERMAL
 
-#define CONFIG_FSL_QSPI
 #ifdef CONFIG_FSL_QSPI
 #define CONFIG_SYS_FSL_QSPI_AHB
 #define CONFIG_SF_DEFAULT_BUS		0
diff --git a/include/configs/mx6ul_14x14_evk.h b/include/configs/mx6ul_14x14_evk.h
index 823405f..925a418 100644
--- a/include/configs/mx6ul_14x14_evk.h
+++ b/include/configs/mx6ul_14x14_evk.h
@@ -186,15 +186,11 @@
 #ifndef CONFIG_SYS_DCACHE_OFF
 #endif
 
-#define CONFIG_FSL_QSPI
 #ifdef CONFIG_FSL_QSPI
-#define CONFIG_SPI_FLASH
-#define CONFIG_SPI_FLASH_BAR
 #define CONFIG_SF_DEFAULT_BUS		0
 #define CONFIG_SF_DEFAULT_CS		0
 #define CONFIG_SF_DEFAULT_SPEED	40000000
 #define CONFIG_SF_DEFAULT_MODE		SPI_MODE_0
-#define CONFIG_SPI_FLASH_STMICRO
 #define FSL_QSPI_FLASH_NUM		1
 #define FSL_QSPI_FLASH_SIZE		SZ_32M
 #endif
diff --git a/include/configs/xilinx_zynqmp.h b/include/configs/xilinx_zynqmp.h
index c43ea19..5ed8beb 100644
--- a/include/configs/xilinx_zynqmp.h
+++ b/include/configs/xilinx_zynqmp.h
@@ -75,7 +75,9 @@
 
 /* Diff from config_distro_defaults.h */
 #define CONFIG_SUPPORT_RAW_INITRD
+#if !defined(CONFIG_SPL_BUILD)
 #define CONFIG_ENV_VARS_UBOOT_CONFIG
+#endif
 #define CONFIG_AUTO_COMPLETE
 
 /* PXE */
@@ -108,7 +110,7 @@
 #define CONFIG_SYS_LOAD_ADDR		0x8000000
 
 #if defined(CONFIG_ZYNQMP_USB)
-#define CONFIG_USB_MAX_CONTROLLER_COUNT         1
+#define CONFIG_USB_MAX_CONTROLLER_COUNT         2
 #define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS      2
 #define CONFIG_USB_XHCI_ZYNQMP
 
@@ -136,7 +138,6 @@
 # define DFU_ALT_INFO
 #endif
 
-
 #define CONFIG_BOARD_LATE_INIT
 
 /* Do not preserve environment */
@@ -185,7 +186,6 @@
 #endif
 
 #ifdef CONFIG_SATA_CEVA
-#define CONFIG_AHCI
 #define CONFIG_LIBATA
 #define CONFIG_SCSI_AHCI
 #define CONFIG_SCSI_AHCI_PLAT
@@ -247,13 +247,24 @@
 	DFU_ALT_INFO
 #endif
 
+/* SPL can't handle all huge variables - define just DFU */
+#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_DFU_SUPPORT)
+#undef CONFIG_EXTRA_ENV_SETTINGS
+# define CONFIG_EXTRA_ENV_SETTINGS \
+	"dfu_alt_info_ram=uboot.bin ram 0x8000000 0x1000000;" \
+			  "atf-uboot.ub ram 0x10000000 0x1000000;" \
+			  "Image ram 0x80000 0x3f80000;" \
+			  "system.dtb ram 0x4000000 0x100000\0" \
+	"dfu_bufsiz=0x1000\0"
+#endif
+
 #define CONFIG_SPL_TEXT_BASE		0xfffc0000
 #define CONFIG_SPL_STACK		0xfffffffc
-#define CONFIG_SPL_MAX_SIZE		0x20000
+#define CONFIG_SPL_MAX_SIZE		0x40000
 
 /* Just random location in OCM */
-#define CONFIG_SPL_BSS_START_ADDR	0x1000000
-#define CONFIG_SPL_BSS_MAX_SIZE		0x2000000
+#define CONFIG_SPL_BSS_START_ADDR	0x0
+#define CONFIG_SPL_BSS_MAX_SIZE		0x80000
 
 #define CONFIG_SPL_FRAMEWORK
 #define CONFIG_SPL_BOARD_INIT
@@ -265,7 +276,7 @@
 #define CONFIG_SYS_SPL_ARGS_ADDR	0x8000000
 
 /* ATF is my kernel image */
-#define CONFIG_SPL_FS_LOAD_KERNEL_NAME	"atf.ub"
+#define CONFIG_SPL_FS_LOAD_KERNEL_NAME	"atf-uboot.ub"
 
 /* FIT load address for RAM boot */
 #define CONFIG_SPL_LOAD_FIT_ADDRESS	0x10000000
@@ -279,4 +290,18 @@
 # define CONFIG_SPL_FS_LOAD_PAYLOAD_NAME	"u-boot.img"
 #endif
 
+#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_DFU_SUPPORT)
+# undef CONFIG_CMD_BOOTD
+# define CONFIG_SPL_ENV_SUPPORT
+# define CONFIG_SPL_HASH_SUPPORT
+# define CONFIG_ENV_MAX_ENTRIES	10
+
+# define CONFIG_SYS_SPL_MALLOC_START	0x20000000
+# define CONFIG_SYS_SPL_MALLOC_SIZE	0x10000000
+
+#ifdef CONFIG_SPL_SYS_MALLOC_SIMPLE
+# error "Disable CONFIG_SPL_SYS_MALLOC_SIMPLE. Full malloc needs to be used"
+#endif
+#endif
+
 #endif /* __XILINX_ZYNQMP_H */
diff --git a/include/configs/xilinx_zynqmp_ep.h b/include/configs/xilinx_zynqmp_ep.h
index 44434aa..8e4b960 100644
--- a/include/configs/xilinx_zynqmp_ep.h
+++ b/include/configs/xilinx_zynqmp_ep.h
@@ -16,7 +16,6 @@
 #define CONFIG_ZYNQ_SDHCI_MAX_FREQ	52000000
 #define CONFIG_ZYNQ_SDHCI_MIN_FREQ	(CONFIG_ZYNQ_SDHCI_MAX_FREQ << 9)
 #define CONFIG_ZYNQ_EEPROM
-#define CONFIG_AHCI
 #define CONFIG_SATA_CEVA
 #define CONFIG_ZYNQMP_XHCI_LIST {ZYNQMP_USB0_XHCI_BASEADDR, \
 				 ZYNQMP_USB1_XHCI_BASEADDR}
diff --git a/include/configs/xilinx_zynqmp_zc1751_xm018_dc4.h b/include/configs/xilinx_zynqmp_zc1751_xm018_dc4.h
deleted file mode 100644
index 4866b61..0000000
--- a/include/configs/xilinx_zynqmp_zc1751_xm018_dc4.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Configuration for Xilinx ZynqMP zc1751 XM018 DC4
- *
- * (C) Copyright 2015 Xilinx, Inc.
- * Michal Simek <michal.simek@xilinx.com>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#ifndef __CONFIG_ZYNQMP_ZC1751_XM018_DC4_H
-#define __CONFIG_ZYNQMP_ZC1751_XM018_DC4_H
-
-#include <configs/xilinx_zynqmp.h>
-
-#endif /* __CONFIG_ZYNQMP_ZC1751_XM018_DC4_H */
diff --git a/include/dt-bindings/clock/boston-clock.h b/include/dt-bindings/clock/boston-clock.h
new file mode 100644
index 0000000..25f9cd2
--- /dev/null
+++ b/include/dt-bindings/clock/boston-clock.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright (C) 2016 Imagination Technologies
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_BOSTON_CLOCK_H__
+#define __DT_BINDINGS_CLOCK_BOSTON_CLOCK_H__
+
+#define BOSTON_CLK_SYS 0
+#define BOSTON_CLK_CPU 1
+
+#endif /* __DT_BINDINGS_CLOCK_BOSTON_CLOCK_H__ */
diff --git a/include/dt-bindings/interrupt-controller/mips-gic.h b/include/dt-bindings/interrupt-controller/mips-gic.h
new file mode 100644
index 0000000..cf35a57
--- /dev/null
+++ b/include/dt-bindings/interrupt-controller/mips-gic.h
@@ -0,0 +1,9 @@
+#ifndef _DT_BINDINGS_INTERRUPT_CONTROLLER_MIPS_GIC_H
+#define _DT_BINDINGS_INTERRUPT_CONTROLLER_MIPS_GIC_H
+
+#include <dt-bindings/interrupt-controller/irq.h>
+
+#define GIC_SHARED 0
+#define GIC_LOCAL 1
+
+#endif
diff --git a/include/mmc.h b/include/mmc.h
index aa6d5d1..e815eb3 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -11,6 +11,7 @@
 #define _MMC_H_
 
 #include <linux/list.h>
+#include <linux/sizes.h>
 #include <linux/compiler.h>
 #include <part.h>
 
@@ -102,6 +103,7 @@
 #define SD_CMD_SWITCH_UHS18V		11
 
 #define SD_CMD_APP_SET_BUS_WIDTH	6
+#define SD_CMD_APP_SD_STATUS		13
 #define SD_CMD_ERASE_WR_BLK_START	32
 #define SD_CMD_ERASE_WR_BLK_END		33
 #define SD_CMD_APP_SEND_OP_COND		41
@@ -392,6 +394,12 @@
 	unsigned char part_type;
 };
 
+struct sd_ssr {
+	unsigned int au;		/* In sectors */
+	unsigned int erase_timeout;	/* In milliseconds */
+	unsigned int erase_offset;	/* In milliseconds */
+};
+
 /*
  * With CONFIG_DM_MMC enabled, struct mmc can be accessed from the MMC device
  * with mmc_get_mmc_dev().
@@ -426,6 +434,7 @@
 	uint write_bl_len;
 	uint erase_grp_size;	/* in 512-byte sectors */
 	uint hc_wp_grp_size;	/* in 512-byte sectors */
+	struct sd_ssr	ssr;	/* SD status register */
 	u64 capacity;
 	u64 capacity_user;
 	u64 capacity_boot;
diff --git a/include/sdhci.h b/include/sdhci.h
index 6844c73..144570f 100644
--- a/include/sdhci.h
+++ b/include/sdhci.h
@@ -97,6 +97,7 @@
 #define  SDHCI_DIV_MASK	0xFF
 #define  SDHCI_DIV_MASK_LEN	8
 #define  SDHCI_DIV_HI_MASK	0x300
+#define  SDHCI_PROG_CLOCK_MODE  0x0020
 #define  SDHCI_CLOCK_CARD_EN	0x0004
 #define  SDHCI_CLOCK_INT_STABLE	0x0002
 #define  SDHCI_CLOCK_INT_EN	0x0001
@@ -242,6 +243,7 @@
 	unsigned int quirks;
 	unsigned int host_caps;
 	unsigned int version;
+	unsigned int clk_mul;   /* Clock Multiplier value */
 	unsigned int clock;
 	struct mmc *mmc;
 	const struct sdhci_ops *ops;
diff --git a/include/spi.h b/include/spi.h
index ca96fa4..4c17983 100644
--- a/include/spi.h
+++ b/include/spi.h
@@ -26,12 +26,9 @@
 #define SPI_TX_BYTE	BIT(8)			/* transmit with 1 wire byte */
 #define SPI_TX_DUAL	BIT(9)			/* transmit with 2 wires */
 #define SPI_TX_QUAD	BIT(10)			/* transmit with 4 wires */
-
-/* SPI mode_rx flags */
-#define SPI_RX_SLOW	BIT(0)			/* receive with 1 wire slow */
-#define SPI_RX_FAST	BIT(1)			/* receive with 1 wire fast */
-#define SPI_RX_DUAL	BIT(2)			/* receive with 2 wires */
-#define SPI_RX_QUAD	BIT(3)			/* receive with 4 wires */
+#define SPI_RX_SLOW	BIT(11)			/* receive with 1 wire slow */
+#define SPI_RX_DUAL	BIT(12)			/* receive with 2 wires */
+#define SPI_RX_QUAD	BIT(13)			/* receive with 4 wires */
 
 /* SPI bus connection options - see enum spi_dual_flash */
 #define SPI_CONN_DUAL_SHARED		(1 << 0)
@@ -61,13 +58,11 @@
  * @cs:		Chip select number (0..n-1)
  * @max_hz:	Maximum bus speed that this slave can tolerate
  * @mode:	SPI mode to use for this device (see SPI mode flags)
- * @mode_rx:	SPI RX mode to use for this slave (see SPI mode_rx flags)
  */
 struct dm_spi_slave_platdata {
 	unsigned int cs;
 	uint max_hz;
 	uint mode;
-	u8 mode_rx;
 };
 
 #endif /* CONFIG_DM_SPI */
@@ -94,7 +89,6 @@
  *			bus (bus->seq) so does not need to be stored
  * @cs:			ID of the chip select connected to the slave.
  * @mode:		SPI mode to use for this slave (see SPI mode flags)
- * @mode_rx:		SPI RX mode to use for this slave (see SPI mode_rx flags)
  * @wordlen:		Size of SPI word in number of bits
  * @max_write_size:	If non-zero, the maximum number of bytes which can
  *			be written at once, excluding command bytes.
@@ -112,7 +106,6 @@
 	unsigned int cs;
 #endif
 	uint mode;
-	u8 mode_rx;
 	unsigned int wordlen;
 	unsigned int max_write_size;
 	void *memory_map;
diff --git a/include/xilinx.h b/include/xilinx.h
index aebcb3b..d2a2ea7 100644
--- a/include/xilinx.h
+++ b/include/xilinx.h
@@ -21,6 +21,7 @@
 	master_selectmap,	/* master SelectMap (virtex2)           */
 	slave_selectmap,	/* slave SelectMap (virtex2)            */
 	devcfg,			/* devcfg interface (zynq) */
+	csu_dma,		/* csu_dma interface (zynqmp) */
 	max_xilinx_iface_type	/* insert all new types before this */
 } xilinx_iface;			/* end, typedef xilinx_iface */
 
@@ -31,6 +32,7 @@
 	xilinx_virtex2,		/* Virtex2 Family */
 	xilinx_spartan3,	/* Spartan-III Family */
 	xilinx_zynq,		/* Zynq Family */
+	xilinx_zynqmp,		/* ZynqMP Family */
 	max_xilinx_type		/* insert all new types before this */
 } xilinx_family;		/* end, typedef xilinx_family */
 
diff --git a/include/zynqmppl.h b/include/zynqmppl.h
new file mode 100644
index 0000000..542ace9
--- /dev/null
+++ b/include/zynqmppl.h
@@ -0,0 +1,24 @@
+/*
+ * (C) Copyright 2015 Xilinx, Inc,
+ * Michal Simek <michal.simek@xilinx.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef _ZYNQMPPL_H_
+#define _ZYNQMPPL_H_
+
+#include <xilinx.h>
+
+#define ZYNQMP_SIP_SVC_CSU_DMA_CHIPID		0xC2000018
+#define ZYNQMP_SIP_SVC_PM_FPGA_LOAD		0xC2000016
+#define ZYNQMP_FPGA_OP_INIT			(1 << 0)
+#define ZYNQMP_FPGA_OP_LOAD			(1 << 1)
+#define ZYNQMP_FPGA_OP_DONE			(1 << 2)
+
+extern struct xilinx_fpga_op zynqmp_op;
+
+#define XILINX_ZYNQMP_DESC \
+{ xilinx_zynqmp, csu_dma, 1, &zynqmp_op, 0, &zynqmp_op }
+
+#endif /* _ZYNQMPPL_H_ */
diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl
index 4994fa8..5a7f79c 100644
--- a/scripts/Makefile.spl
+++ b/scripts/Makefile.spl
@@ -216,8 +216,19 @@
 cmd_cpp_cfg = $(CPP) -Wp,-MD,$(depfile) $(cpp_flags) $(LDPPFLAGS) -ansi \
 	-DDO_DEPS_ONLY -D__ASSEMBLY__ -x assembler-with-cpp -P -dM -E -o $@ $<
 
+# If .u-boot.cfg.d is still present, then either:
+# a) The previous build used a Makefile that used if_changed rather than
+#    if_changed_dep when building u-boot.cfg, and hence any later builds will
+#    be unaware of the dependencies for u-boot.cfg. In this case, we must
+#    delete u-boot.cfg to force it and .u-boot.cfg.cmd to be rebuilt the
+#    correct way.
+# b) The previous build failed or was interrupted while building u-boot.cfg,
+#    so deleting u-boot.cfg isn't going to cause any additional work.
+ifneq ($(wildcard $(obj)/.$(SPL_BIN).d),)
+  unused := $(shell rm -f $(obj)/$(SPL_BIN).cfg)
+endif
 $(obj)/$(SPL_BIN).cfg:	include/config.h FORCE
-	$(call if_changed,cpp_cfg)
+	$(call if_changed_dep,cpp_cfg)
 
 pythonpath = PYTHONPATH=tools
 
diff --git a/test/py/tests/test_vboot.py b/test/py/tests/test_vboot.py
index 021892b..6e62820 100644
--- a/test/py/tests/test_vboot.py
+++ b/test/py/tests/test_vboot.py
@@ -53,7 +53,7 @@
         util.run_and_log(cons, 'dtc %s %s%s -O dtb '
                          '-o %s%s' % (dtc_args, datadir, dts, tmpdir, dtb))
 
-    def run_bootm(sha_algo, test_type, expect_string):
+    def run_bootm(sha_algo, test_type, expect_string, boots):
         """Run a 'bootm' command U-Boot.
 
         This always starts a fresh U-Boot instance since the device tree may
@@ -64,6 +64,8 @@
             expect_string: A string which is expected in the output.
             sha_algo: Either 'sha1' or 'sha256', to select the algorithm to
                     use.
+            boots: A boolean that is True if Linux should boot and False if
+                    we are expected to not boot
         """
         cons.restart_uboot()
         with cons.log.section('Verified boot %s %s' % (sha_algo, test_type)):
@@ -72,6 +74,8 @@
                 'fdt addr 100',
                 'bootm 100'])
         assert(expect_string in ''.join(output))
+        if boots:
+            assert('sandbox: continuing, as we cannot run' in ''.join(output))
 
     def make_fit(its):
         """Make a new FIT from the .its source file.
@@ -117,22 +121,22 @@
         # Build the FIT, but don't sign anything yet
         cons.log.action('%s: Test FIT with signed images' % sha_algo)
         make_fit('sign-images-%s.its' % sha_algo)
-        run_bootm(sha_algo, 'unsigned images', 'dev-')
+        run_bootm(sha_algo, 'unsigned images', 'dev-', True)
 
         # Sign images with our dev keys
         sign_fit(sha_algo)
-        run_bootm(sha_algo, 'signed images', 'dev+')
+        run_bootm(sha_algo, 'signed images', 'dev+', True)
 
         # Create a fresh .dtb without the public keys
         dtc('sandbox-u-boot.dts')
 
         cons.log.action('%s: Test FIT with signed configuration' % sha_algo)
         make_fit('sign-configs-%s.its' % sha_algo)
-        run_bootm(sha_algo, 'unsigned config', '%s+ OK' % sha_algo)
+        run_bootm(sha_algo, 'unsigned config', '%s+ OK' % sha_algo, True)
 
         # Sign images with our dev keys
         sign_fit(sha_algo)
-        run_bootm(sha_algo, 'signed config', 'dev+')
+        run_bootm(sha_algo, 'signed config', 'dev+', True)
 
         cons.log.action('%s: Check signed config on the host' % sha_algo)
 
@@ -149,7 +153,7 @@
         util.run_and_log(cons, 'fdtput -t bx %s %s value %s' %
                          (fit, sig_node, sig))
 
-        run_bootm(sha_algo, 'Signed config with bad hash', 'Bad Data Hash')
+        run_bootm(sha_algo, 'Signed config with bad hash', 'Bad Data Hash', False)
 
         cons.log.action('%s: Check bad config on the host' % sha_algo)
         util.run_and_log_expect_exception(cons, [fit_check_sign, '-f', fit,