diff --git a/MAINTAINERS b/MAINTAINERS
index 607bc9cbdbde5245d4a2362d226394b2cbf4accd..9ab5428dcb108bad934998634c84815d3199c90c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -93,12 +93,14 @@ F:	arch/arm/include/asm/arch-mx*/
 F:	arch/arm/include/asm/arch-vf610/
 F:	arch/arm/include/asm/imx-common/
 
-ARM MARVELL KIRKWOOD
+ARM MARVELL KIRKWOOD ARMADA-XP ARMADA-38X
 M:	Prafulla Wadaskar <prafulla@marvell.com>
 M:	Luka Perkov <luka.perkov@sartura.hr>
+M:	Stefan Roese <sr@denx.de>
 S:	Maintained
 T:	git git://git.denx.de/u-boot-marvell.git
 F:	arch/arm/mach-kirkwood/
+F:	arch/arm/mach-mvebu/
 
 ARM MARVELL PXA
 M:	Marek Vasut <marex@denx.de>
diff --git a/Makefile b/Makefile
index 100de92eab59fc7e6a96e96005ac2fca9f67be0d..5882c30771ab980c702c6185eff745e0c42d2529 100644
--- a/Makefile
+++ b/Makefile
@@ -915,18 +915,8 @@ MKIMAGEFLAGS_u-boot.pbl = -n $(srctree)/$(CONFIG_SYS_FSL_PBL_RCW:"%"=%) \
 u-boot.img u-boot.kwb u-boot.pbl: u-boot.bin FORCE
 	$(call if_changed,mkimage)
 
-# If the kwboot xmodem protocol is used, to boot U-Boot on the MVEBU
-# SoC's, the SPL U-Boot returns to the BootROM after it completes
-# the SDRAM setup. The BootROM expects no U-Boot header in the main
-# U-Boot image. So we need to combine SPL and u-boot.bin instead of
-# u-boot.img in this case.
-ifdef CONFIG_MVEBU_BOOTROM_UARTBOOT
-u-boot-spl.kwb: u-boot-dtb.bin spl/u-boot-spl.bin FORCE
-	$(call if_changed,mkimage)
-else
 u-boot-spl.kwb: u-boot-dtb.img spl/u-boot-spl.bin FORCE
 	$(call if_changed,mkimage)
-endif
 
 MKIMAGEFLAGS_u-boot-dtb.img = $(MKIMAGEFLAGS_u-boot.img)
 
diff --git a/README b/README
index 5ac2d445679b90c69a88e581014e27e119394022..9423c349c9a5b3366fc931bcc5881cb9e897f009 100644
--- a/README
+++ b/README
@@ -5118,14 +5118,11 @@ If the system board that you have is not listed, then you will need
 to port U-Boot to your hardware platform. To do this, follow these
 steps:
 
-1.  Add a new configuration option for your board to the toplevel
-    "boards.cfg" file, using the existing entries as examples.
-    Follow the instructions there to keep the boards in order.
-2.  Create a new directory to hold your board specific code. Add any
+1.  Create a new directory to hold your board specific code. Add any
     files you need. In your board directory, you will need at least
-    the "Makefile", a "<board>.c", "flash.c" and "u-boot.lds".
-3.  Create a new configuration file "include/configs/<board>.h" for
-    your board
+    the "Makefile" and a "<board>.c".
+2.  Create a new configuration file "include/configs/<board>.h" for
+    your board.
 3.  If you're porting U-Boot to a new CPU, then also create a new
     directory to hold your CPU specific code. Add any files you need.
 4.  Run "make <board>_defconfig" with your new name.
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 52b300d4831d81922b83fbe46ba20e478f377207..dd9cac91e7e77c43411505d31976e75a81a58472 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -117,8 +117,14 @@ config ARCH_MVEBU
 	select OF_CONTROL
 	select OF_SEPARATE
 	select DM
+	select DM_ETH
 	select DM_SERIAL
+	select DM_SPI
+	select DM_SPI_FLASH
+	select SPL_DM
 	select SPL_DM_SEQ_ALIAS
+	select SPL_OF_CONTROL
+	select SPL_SIMPLE_BUS
 
 config TARGET_DEVKIT3250
 	bool "Support devkit3250"
@@ -770,8 +776,6 @@ source "board/BuR/kwb/Kconfig"
 source "board/BuR/tseries/Kconfig"
 source "board/CarMediaLab/flea3/Kconfig"
 source "board/Marvell/aspenite/Kconfig"
-source "board/Marvell/db-88f6820-gp/Kconfig"
-source "board/Marvell/db-mv784mp-gp/Kconfig"
 source "board/Marvell/gplugd/Kconfig"
 source "board/armadeus/apf27/Kconfig"
 source "board/armltd/vexpress/Kconfig"
@@ -810,7 +814,6 @@ source "board/h2200/Kconfig"
 source "board/hisilicon/hikey/Kconfig"
 source "board/imx31_phycore/Kconfig"
 source "board/isee/igep0033/Kconfig"
-source "board/maxbcm/Kconfig"
 source "board/mpl/vcma9/Kconfig"
 source "board/olimex/mx23_olinuxino/Kconfig"
 source "board/phytec/pcm051/Kconfig"
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 18283d1d359fd1f860dc5d2545ce30849fa00bae..3d156732139e5de1f847a12a0dc6b49f5825d2c1 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -49,7 +49,7 @@ machine-$(CONFIG_ARCH_HIGHBANK)		+= highbank
 machine-$(CONFIG_ARCH_KEYSTONE)		+= keystone
 # TODO: rename CONFIG_KIRKWOOD -> CONFIG_ARCH_KIRKWOOD
 machine-$(CONFIG_KIRKWOOD)		+= kirkwood
-machine-$(CONFIG_ARMADA_XP)		+= mvebu
+machine-$(CONFIG_ARCH_MVEBU)		+= mvebu
 # TODO: rename CONFIG_TEGRA -> CONFIG_ARCH_TEGRA
 # TODO: rename CONFIG_ORION5X -> CONFIG_ARCH_ORION5X
 machine-$(CONFIG_ORION5X)		+= orion5x
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 0bcd31637560a25ef341f6069b5c018e2682fcaf..64b837114121e362772df0b3feb6fd973d262095 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -48,8 +48,11 @@ dtb-$(CONFIG_TEGRA) += tegra20-harmony.dtb \
 	tegra210-p2571.dtb
 
 dtb-$(CONFIG_ARCH_MVEBU) +=			\
+	armada-388-clearfog.dtb			\
 	armada-388-gp.dtb			\
-	armada-xp-gp.dtb
+	armada-xp-gp.dtb			\
+	armada-xp-maxbcm.dtb			\
+	armada-xp-synology-ds414.dtb
 
 dtb-$(CONFIG_ARCH_UNIPHIER) += \
 	uniphier-ph1-ld4-ref.dtb \
diff --git a/arch/arm/dts/armada-370-xp.dtsi b/arch/arm/dts/armada-370-xp.dtsi
index a718866ba52d8e827653c7cbcb3341778f480b83..0b2a78d393010fbdbfb400ddad63a4dba2d9ff18 100644
--- a/arch/arm/dts/armada-370-xp.dtsi
+++ b/arch/arm/dts/armada-370-xp.dtsi
@@ -141,6 +141,7 @@
 			#address-cells = <1>;
 			#size-cells = <1>;
 			ranges = <0 MBUS_ID(0xf0, 0x01) 0 0x100000>;
+			u-boot,dm-pre-reloc;
 
 			rtc@10300 {
 				compatible = "marvell,orion-rtc";
diff --git a/arch/arm/dts/armada-388-clearfog.dts b/arch/arm/dts/armada-388-clearfog.dts
new file mode 100644
index 0000000000000000000000000000000000000000..b2dfd5643521ac8eb213f60e631db0b3f19d8b2f
--- /dev/null
+++ b/arch/arm/dts/armada-388-clearfog.dts
@@ -0,0 +1,509 @@
+/*
+ * Device Tree file for SolidRun Clearfog revision A1 rev 2.0 (88F6828)
+ *
+ *  Copyright (C) 2015 Russell King
+ *
+ * This board is in development; the contents of this file work with
+ * the A1 rev 2.0 of the board, which does not represent final
+ * production board.  Things will change, don't expect this file to
+ * remain compatible info the future.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     version 2 as published by the Free Software Foundation.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/gpio/gpio.h>
+#include "armada-388.dtsi"
+
+/ {
+	model = "SolidRun Clearfog A1";
+	compatible = "solidrun,clearfog-a1", "marvell,armada388",
+		"marvell,armada385", "marvell,armada380";
+
+	aliases {
+		/* So that mvebu u-boot can update the MAC addresses */
+		ethernet1 = &eth0;
+		ethernet2 = &eth1;
+		ethernet3 = &eth2;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x10000000>; /* 256 MB */
+	};
+
+	reg_3p3v: regulator-3p3v {
+		compatible = "regulator-fixed";
+		regulator-name = "3P3V";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+	};
+
+	soc {
+		ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000
+			  MBUS_ID(0x01, 0x1d) 0 0xfff00000 0x100000
+			  MBUS_ID(0x09, 0x19) 0 0xf1100000 0x10000
+			  MBUS_ID(0x09, 0x15) 0 0xf1110000 0x10000>;
+
+		internal-regs {
+			ethernet@30000 {
+				mac-address = [00 50 43 02 02 02];
+				phy-mode = "sgmii";
+				status = "okay";
+
+				fixed-link {
+					speed = <1000>;
+					full-duplex;
+				};
+			};
+
+			ethernet@34000 {
+				mac-address = [00 50 43 02 02 03];
+				managed = "in-band-status";
+				phy-mode = "sgmii";
+				status = "okay";
+			};
+
+			ethernet@70000 {
+				mac-address = [00 50 43 02 02 01];
+				pinctrl-0 = <&ge0_rgmii_pins>;
+				pinctrl-names = "default";
+				phy = <&phy_dedicated>;
+				phy-mode = "rgmii-id";
+				status = "okay";
+			};
+
+			i2c@11000 {
+				/* Is there anything on this? */
+				clock-frequency = <100000>;
+				pinctrl-0 = <&i2c0_pins>;
+				pinctrl-names = "default";
+				status = "okay";
+
+				/*
+				 * PCA9655 GPIO expander, up to 1MHz clock.
+				 *  0-CON3 CLKREQ#
+				 *  1-CON3 PERST#
+				 *  2-CON2 PERST#
+				 *  3-CON3 W_DISABLE
+				 *  4-CON2 CLKREQ#
+				 *  5-USB3 overcurrent
+				 *  6-USB3 power
+				 *  7-CON2 W_DISABLE
+				 *  8-JP4 P1
+				 *  9-JP4 P4
+				 * 10-JP4 P5
+				 * 11-m.2 DEVSLP
+				 * 12-SFP_LOS
+				 * 13-SFP_TX_FAULT
+				 * 14-SFP_TX_DISABLE
+				 * 15-SFP_MOD_DEF0
+				 */
+				expander0: gpio-expander@20 {
+					/*
+					 * This is how it should be:
+					 * compatible = "onnn,pca9655",
+					 *	 "nxp,pca9555";
+					 * but you can't do this because of
+					 * the way I2C works.
+					 */
+					compatible = "nxp,pca9555";
+					gpio-controller;
+					#gpio-cells = <2>;
+					reg = <0x20>;
+
+					pcie1_0_clkreq {
+						gpio-hog;
+						gpios = <0 GPIO_ACTIVE_LOW>;
+						input;
+						line-name = "pcie1.0-clkreq";
+					};
+					pcie1_0_w_disable {
+						gpio-hog;
+						gpios = <3 GPIO_ACTIVE_LOW>;
+						output-low;
+						line-name = "pcie1.0-w-disable";
+					};
+					pcie2_0_clkreq {
+						gpio-hog;
+						gpios = <4 GPIO_ACTIVE_LOW>;
+						input;
+						line-name = "pcie2.0-clkreq";
+					};
+					pcie2_0_w_disable {
+						gpio-hog;
+						gpios = <7 GPIO_ACTIVE_LOW>;
+						output-low;
+						line-name = "pcie2.0-w-disable";
+					};
+					usb3_ilimit {
+						gpio-hog;
+						gpios = <5 GPIO_ACTIVE_LOW>;
+						input;
+						line-name = "usb3-current-limit";
+					};
+					usb3_power {
+						gpio-hog;
+						gpios = <6 GPIO_ACTIVE_HIGH>;
+						output-high;
+						line-name = "usb3-power";
+					};
+					m2_devslp {
+						gpio-hog;
+						gpios = <11 GPIO_ACTIVE_HIGH>;
+						output-low;
+						line-name = "m.2 devslp";
+					};
+				};
+
+				/* The MCP3021 is 100kHz clock only */
+				mikrobus_adc: mcp3021@4c {
+					compatible = "microchip,mcp3021";
+					reg = <0x4c>;
+				};
+
+				/* Also something at 0x64 */
+			};
+
+			i2c@11100 {
+				/*
+				 * Routed to SFP, mikrobus, and PCIe.
+				 * SFP limits this to 100kHz, and requires
+				 *  an AT24C01A/02/04 with address pins tied
+				 *  low, which takes addresses 0x50 and 0x51.
+				 * Mikrobus doesn't specify beyond an I2C
+				 *  bus being present.
+				 * PCIe uses ARP to assign addresses, or
+				 *  0x63-0x64.
+				 */
+				clock-frequency = <100000>;
+				pinctrl-0 = <&clearfog_i2c1_pins>;
+				pinctrl-names = "default";
+				status = "okay";
+			};
+
+			mdio@72004 {
+				pinctrl-0 = <&mdio_pins>;
+				pinctrl-names = "default";
+
+				phy_dedicated: ethernet-phy@0 {
+					/*
+					 * Annoyingly, the marvell phy driver
+					 * configures the LED register, rather
+					 * than preserving reset-loaded setting.
+					 * We undo that rubbish here.
+					 */
+					marvell,reg-init = <3 16 0 0x101e>;
+					reg = <0>;
+				};
+			};
+
+			pinctrl@18000 {
+				clearfog_dsa0_clk_pins: clearfog-dsa0-clk-pins {
+					marvell,pins = "mpp46";
+					marvell,function = "ref";
+				};
+				clearfog_dsa0_pins: clearfog-dsa0-pins {
+					marvell,pins = "mpp23", "mpp41";
+					marvell,function = "gpio";
+				};
+				clearfog_i2c1_pins: i2c1-pins {
+					/* SFP, PCIe, mSATA, mikrobus */
+					marvell,pins = "mpp26", "mpp27";
+					marvell,function = "i2c1";
+				};
+				clearfog_sdhci_cd_pins: clearfog-sdhci-cd-pins {
+					marvell,pins = "mpp20";
+					marvell,function = "gpio";
+				};
+				clearfog_sdhci_pins: clearfog-sdhci-pins {
+					marvell,pins = "mpp21", "mpp28",
+						       "mpp37", "mpp38",
+						       "mpp39", "mpp40";
+					marvell,function = "sd0";
+				};
+				clearfog_spi1_cs_pins: spi1-cs-pins {
+					marvell,pins = "mpp55";
+					marvell,function = "spi1";
+				};
+				mikro_pins: mikro-pins {
+					/* int: mpp22 rst: mpp29 */
+					marvell,pins = "mpp22", "mpp29";
+					marvell,function = "gpio";
+				};
+				mikro_spi_pins: mikro-spi-pins {
+					marvell,pins = "mpp43";
+					marvell,function = "spi1";
+				};
+				mikro_uart_pins: mikro-uart-pins {
+					marvell,pins = "mpp24", "mpp25";
+					marvell,function = "ua1";
+				};
+				rear_button_pins: rear-button-pins {
+					marvell,pins = "mpp34";
+					marvell,function = "gpio";
+				};
+			};
+
+			rtc@a3800 {
+				/*
+				 * If the rtc doesn't work, run "date reset"
+				 * twice in u-boot.
+				 */
+				status = "okay";
+			};
+
+			sata@a8000 {
+				/* pinctrl? */
+				status = "okay";
+			};
+
+			sata@e0000 {
+				/* pinctrl? */
+				status = "okay";
+			};
+
+			sdhci@d8000 {
+				bus-width = <4>;
+				cd-gpios = <&gpio0 20 GPIO_ACTIVE_LOW>;
+				no-1-8-v;
+				pinctrl-0 = <&clearfog_sdhci_pins
+					     &clearfog_sdhci_cd_pins>;
+				pinctrl-names = "default";
+				status = "okay";
+				vmmc = <&reg_3p3v>;
+				wp-inverted;
+			};
+
+			serial@12000 {
+				pinctrl-0 = <&uart0_pins>;
+				pinctrl-names = "default";
+				status = "okay";
+				u-boot,dm-pre-reloc;
+			};
+
+			serial@12100 {
+				/* mikrobus uart */
+				pinctrl-0 = <&mikro_uart_pins>;
+				pinctrl-names = "default";
+				status = "okay";
+			};
+
+			spi@10680 {
+				/*
+				 * We don't seem to have the W25Q32 on the
+				 * A1 Rev 2.0 boards, so disable SPI.
+				 * CS0: W25Q32 (doesn't appear to be present)
+				 * CS1:
+				 * CS2: mikrobus
+				 */
+				pinctrl-0 = <&spi1_pins &clearfog_spi1_cs_pins &mikro_spi_pins>;
+				pinctrl-names = "default";
+				status = "okay";
+
+				spi-flash@0 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					compatible = "w25q32", "jedec,spi-nor";
+					reg = <0>; /* Chip select 0 */
+					spi-max-frequency = <3000000>;
+					status = "disabled";
+				};
+			};
+
+			usb3@f8000 {
+				status = "okay";
+			};
+		};
+
+		pcie-controller {
+			status = "okay";
+			/*
+			 * The two PCIe units are accessible through
+			 * the mini-PCIe connectors on the board.
+			 */
+			pcie@2,0 {
+				/* Port 1, Lane 0. CONN3, nearest power. */
+				reset-gpios = <&expander0 1 GPIO_ACTIVE_LOW>;
+				status = "okay";
+			};
+			pcie@3,0 {
+				/* Port 2, Lane 0. CONN2, nearest CPU. */
+				reset-gpios = <&expander0 2 GPIO_ACTIVE_LOW>;
+				status = "okay";
+			};
+		};
+	};
+
+	sfp: sfp {
+		compatible = "sff,sfp";
+		i2c-bus = <&i2c1>;
+		los-gpio = <&expander0 12 GPIO_ACTIVE_HIGH>;
+		moddef0-gpio = <&expander0 15 GPIO_ACTIVE_LOW>;
+		sfp,ethernet = <&eth2>;
+		tx-disable-gpio = <&expander0 14 GPIO_ACTIVE_HIGH>;
+		tx-fault-gpio = <&expander0 13 GPIO_ACTIVE_HIGH>;
+	};
+
+	dsa@0 {
+		compatible = "marvell,dsa";
+		dsa,ethernet = <&eth1>;
+		dsa,mii-bus = <&mdio>;
+		pinctrl-0 = <&clearfog_dsa0_clk_pins &clearfog_dsa0_pins>;
+		pinctrl-names = "default";
+		#address-cells = <2>;
+		#size-cells = <0>;
+
+		switch@0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <4 0>;
+
+			port@0 {
+				reg = <0>;
+				label = "lan1";
+			};
+
+			port@1 {
+				reg = <1>;
+				label = "lan2";
+			};
+
+			port@2 {
+				reg = <2>;
+				label = "lan3";
+			};
+
+			port@3 {
+				reg = <3>;
+				label = "lan4";
+			};
+
+			port@4 {
+				reg = <4>;
+				label = "lan5";
+			};
+
+			port@5 {
+				reg = <5>;
+				label = "cpu";
+			};
+
+			port@6 {
+				/* 88E1512 external phy */
+				reg = <6>;
+				label = "lan6";
+				fixed-link {
+					speed = <1000>;
+					full-duplex;
+				};
+			};
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		pinctrl-0 = <&rear_button_pins>;
+		pinctrl-names = "default";
+
+		button_0 {
+			/* The rear SW3 button */
+			label = "Rear Button";
+			gpios = <&gpio1 2 GPIO_ACTIVE_LOW>;
+			linux,can-disable;
+			linux,code = <BTN_0>;
+		};
+	};
+};
+
+/*
++#define A38x_CUSTOMER_BOARD_1_MPP16_23         0x00400011
+MPP18: gpio		? (pca9655 int?)
+MPP19: gpio		? (clkreq?)
+MPP20: gpio		? (sd0 detect)
+MPP21: sd0:cmd		x sd0
+MPP22: gpio		x mikro int
+MPP23: gpio		x switch irq
++#define A38x_CUSTOMER_BOARD_1_MPP24_31         0x22043333
+MPP24: ua1:rxd		x mikro rx
+MPP25: ua1:txd		x mikro tx
+MPP26: i2c1:sck		x mikro sck
+MPP27: i2c1:sda		x mikro sda
+MPP28: sd0:clk		x sd0
+MPP29: gpio		x mikro rst
+MPP30: ge1:txd2		? (config)
+MPP31: ge1:txd3		? (config)
++#define A38x_CUSTOMER_BOARD_1_MPP32_39         0x44400002
+MPP32: ge1:txctl	? (unused)
+MPP33: gpio		? (pic_com0)
+MPP34: gpio		x rear button (pic_com1)
+MPP35: gpio		? (pic_com2)
+MPP36: gpio		? (unused)
+MPP37: sd0:d3		x sd0
+MPP38: sd0:d0		x sd0
+MPP39: sd0:d1		x sd0
++#define A38x_CUSTOMER_BOARD_1_MPP40_47         0x41144004
+MPP40: sd0:d2		x sd0
+MPP41: gpio		x switch reset
+MPP42: gpio		? sw1-1
+MPP43: spi1:cs2		x mikro cs
+MPP44: sata3:prsnt	? (unused)
+MPP45: ref:clk_out0	?
+MPP46: ref:clk_out1	x switch clk
+MPP47: 4		? (unused)
++#define A38x_CUSTOMER_BOARD_1_MPP48_55         0x40333333
+MPP48: tdm:pclk
+MPP49: tdm:fsync
+MPP50: tdm:drx
+MPP51: tdm:dtx
+MPP52: tdm:int
+MPP53: tdm:rst
+MPP54: gpio		? (pwm)
+MPP55: spi1:cs1		x slic
++#define A38x_CUSTOMER_BOARD_1_MPP56_63         0x00004444
+MPP56: spi1:mosi	x mikro mosi
+MPP57: spi1:sck		x mikro sck
+MPP58: spi1:miso	x mikro miso
+MPP59: spi1:cs0		x w25q32
+*/
diff --git a/arch/arm/dts/armada-388-gp.dts b/arch/arm/dts/armada-388-gp.dts
index fd4f6fd8a2e8a30277db97ab71bbd5b2a5dfd05d..7bc878f5a926955d9c53ffdbb9fefb5fe2e430bc 100644
--- a/arch/arm/dts/armada-388-gp.dts
+++ b/arch/arm/dts/armada-388-gp.dts
@@ -51,6 +51,12 @@
 		stdout-path = "serial0:115200n8";
 	};
 
+	aliases {
+		ethernet0 = &eth0;
+		ethernet1 = &eth1;
+		spi0 = &spi0;
+	};
+
 	memory {
 		device_type = "memory";
 		reg = <0x00000000 0x80000000>; /* 2 GB */
@@ -65,8 +71,10 @@
 				pinctrl-names = "default";
 				pinctrl-0 = <&spi0_pins>;
 				status = "okay";
+				u-boot,dm-pre-reloc;
 
 				spi-flash@0 {
+					u-boot,dm-pre-reloc;
 					#address-cells = <1>;
 					#size-cells = <1>;
 					compatible = "st,m25p128", "jedec,spi-nor";
@@ -122,6 +130,7 @@
 				pinctrl-names = "default";
 				pinctrl-0 = <&uart0_pins>;
 				status = "okay";
+				u-boot,dm-pre-reloc;
 			};
 
 			/* GE1 CON15 */
diff --git a/arch/arm/dts/armada-38x.dtsi b/arch/arm/dts/armada-38x.dtsi
index 04ecfe6e2bc6e3c47210a9f5af18516b2e0b61d4..dc8a1a66c1fb627d710176fa0cfdb391d6f8d180 100644
--- a/arch/arm/dts/armada-38x.dtsi
+++ b/arch/arm/dts/armada-38x.dtsi
@@ -70,6 +70,7 @@
 
 	soc {
 		compatible = "marvell,armada380-mbus", "simple-bus";
+		u-boot,dm-pre-reloc;
 		#address-cells = <2>;
 		#size-cells = <1>;
 		controller = <&mbusc>;
@@ -134,6 +135,7 @@
 
 		internal-regs {
 			compatible = "simple-bus";
+			u-boot,dm-pre-reloc;
 			#address-cells = <1>;
 			#size-cells = <1>;
 			ranges = <0 MBUS_ID(0xf0, 0x01) 0 0x100000>;
diff --git a/arch/arm/dts/armada-xp-gp.dts b/arch/arm/dts/armada-xp-gp.dts
index bf724ca96a331fa7410e36b7c08169bf360efe92..27799d1254eadc1f9056a17184195449c5cd8624 100644
--- a/arch/arm/dts/armada-xp-gp.dts
+++ b/arch/arm/dts/armada-xp-gp.dts
@@ -68,6 +68,10 @@
 		stdout-path = "serial0:115200n8";
 	};
 
+	aliases {
+		spi0 = &spi0;
+	};
+
 	memory {
 		device_type = "memory";
 		/*
@@ -148,6 +152,7 @@
 		internal-regs {
 			serial@12000 {
 				status = "okay";
+				u-boot,dm-pre-reloc;
 			};
 			serial@12100 {
 				status = "okay";
@@ -223,8 +228,10 @@
 
 			spi0: spi@10600 {
 				status = "okay";
+				u-boot,dm-pre-reloc;
 
 				spi-flash@0 {
+					u-boot,dm-pre-reloc;
 					#address-cells = <1>;
 					#size-cells = <1>;
 					compatible = "n25q128a13", "jedec,spi-nor";
diff --git a/arch/arm/dts/armada-xp-maxbcm.dts b/arch/arm/dts/armada-xp-maxbcm.dts
new file mode 100644
index 0000000000000000000000000000000000000000..d7d7f65c85fec623f7a66fcd4efdc12fa0216d47
--- /dev/null
+++ b/arch/arm/dts/armada-xp-maxbcm.dts
@@ -0,0 +1,249 @@
+/*
+ * Device Tree file for Marvell Armada XP maxbcm board
+ *
+ * Copyright (C) 2013-2014 Marvell
+ *
+ * Lior Amsalem <alior@marvell.com>
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Note: this Device Tree assumes that the bootloader has remapped the
+ * internal registers to 0xf1000000 (instead of the default
+ * 0xd0000000). The 0xf1000000 is the default used by the recent,
+ * DT-capable, U-Boot bootloaders provided by Marvell. Some earlier
+ * boards were delivered with an older version of the bootloader that
+ * left internal registers mapped at 0xd0000000. If you are in this
+ * situation, you should either update your bootloader (preferred
+ * solution) or the below Device Tree should be adjusted.
+ */
+
+/dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
+#include "armada-xp-mv78460.dtsi"
+
+/ {
+	model = "Marvell Armada XP MAXBCM";
+	compatible = "marvell,axp-gp", "marvell,armadaxp-mv78460", "marvell,armadaxp", "marvell,armada-370-xp";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	aliases {
+		spi0 = &spi0;
+	};
+
+	memory {
+		device_type = "memory";
+		/*
+                 * 8 GB of plug-in RAM modules by default.The amount
+                 * of memory available can be changed by the
+                 * bootloader according the size of the module
+                 * actually plugged. However, memory between
+                 * 0xF0000000 to 0xFFFFFFFF cannot be used, as it is
+                 * the address range used for I/O (internal registers,
+                 * MBus windows).
+		 */
+		reg = <0x00000000 0x00000000 0x00000000 0xf0000000>,
+		      <0x00000001 0x00000000 0x00000001 0x00000000>;
+	};
+
+	cpus {
+		pm_pic {
+			ctrl-gpios = <&gpio0 16 GPIO_ACTIVE_LOW>,
+				     <&gpio0 17 GPIO_ACTIVE_LOW>,
+				     <&gpio0 18 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	soc {
+		ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xf1000000 0x100000
+			  MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000
+			  MBUS_ID(0x01, 0x2f) 0 0 0xf0000000 0x1000000>;
+
+		devbus-bootcs {
+			status = "okay";
+
+			/* Device Bus parameters are required */
+
+			/* Read parameters */
+			devbus,bus-width    = <16>;
+			devbus,turn-off-ps  = <60000>;
+			devbus,badr-skew-ps = <0>;
+			devbus,acc-first-ps = <124000>;
+			devbus,acc-next-ps  = <248000>;
+			devbus,rd-setup-ps  = <0>;
+			devbus,rd-hold-ps   = <0>;
+
+			/* Write parameters */
+			devbus,sync-enable = <0>;
+			devbus,wr-high-ps  = <60000>;
+			devbus,wr-low-ps   = <60000>;
+			devbus,ale-wr-ps   = <60000>;
+
+			/* NOR 16 MiB */
+			nor@0 {
+				compatible = "cfi-flash";
+				reg = <0 0x1000000>;
+				bank-width = <2>;
+			};
+		};
+
+		pcie-controller {
+			status = "okay";
+
+			/*
+			 * The 3 slots are physically present as
+			 * standard PCIe slots on the board.
+			 */
+			pcie@1,0 {
+				/* Port 0, Lane 0 */
+				status = "okay";
+			};
+			pcie@9,0 {
+				/* Port 2, Lane 0 */
+				status = "okay";
+			};
+			pcie@10,0 {
+				/* Port 3, Lane 0 */
+				status = "okay";
+			};
+		};
+
+		internal-regs {
+			serial@12000 {
+				status = "okay";
+				u-boot,dm-pre-reloc;
+			};
+			serial@12100 {
+				status = "okay";
+			};
+			serial@12200 {
+				status = "okay";
+			};
+			serial@12300 {
+				status = "okay";
+			};
+			pinctrl {
+				pinctrl-0 = <&pic_pins>;
+				pinctrl-names = "default";
+				pic_pins: pic-pins-0 {
+					marvell,pins = "mpp16", "mpp17",
+						       "mpp18";
+					marvell,function = "gpio";
+				};
+			};
+			sata@a0000 {
+				nr-ports = <2>;
+				status = "okay";
+			};
+
+			mdio {
+				phy0: ethernet-phy@0 {
+					reg = <0>;
+				};
+
+				phy1: ethernet-phy@1 {
+					reg = <1>;
+				};
+
+				phy2: ethernet-phy@2 {
+					reg = <2>;
+				};
+
+				phy3: ethernet-phy@3 {
+					reg = <3>;
+				};
+			};
+
+			ethernet@70000 {
+				status = "okay";
+				phy = <&phy0>;
+				phy-mode = "sgmii";
+			};
+			ethernet@74000 {
+				status = "okay";
+				phy = <&phy1>;
+				phy-mode = "sgmii";
+			};
+			ethernet@30000 {
+				status = "okay";
+				phy = <&phy2>;
+				phy-mode = "sgmii";
+			};
+			ethernet@34000 {
+				status = "okay";
+				phy = <&phy3>;
+				phy-mode = "sgmii";
+			};
+
+			/* Front-side USB slot */
+			usb@50000 {
+				status = "okay";
+			};
+
+			/* Back-side USB slot */
+			usb@51000 {
+				status = "okay";
+			};
+
+			spi0: spi@10600 {
+				status = "okay";
+
+				spi-flash@0 {
+					#address-cells = <1>;
+					#size-cells = <1>;
+					compatible = "n25q128a13", "jedec,spi-nor";
+					reg = <0>; /* Chip select 0 */
+					spi-max-frequency = <108000000>;
+				};
+			};
+
+			nand@d0000 {
+				status = "okay";
+				num-cs = <1>;
+				marvell,nand-keep-config;
+				marvell,nand-enable-arbiter;
+				nand-on-flash-bbt;
+			};
+		};
+	};
+};
diff --git a/arch/arm/dts/armada-xp-synology-ds414.dts b/arch/arm/dts/armada-xp-synology-ds414.dts
new file mode 100644
index 0000000000000000000000000000000000000000..0a60ddfa4149ee75da08ef732bf5699544c7131c
--- /dev/null
+++ b/arch/arm/dts/armada-xp-synology-ds414.dts
@@ -0,0 +1,337 @@
+/*
+ * Device Tree file for Synology DS414
+ *
+ * Copyright (C) 2014, Arnaud EBALARD <arno@natisbad.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Note: this Device Tree assumes that the bootloader has remapped the
+ * internal registers to 0xf1000000 (instead of the old 0xd0000000).
+ * The 0xf1000000 is the default used by the recent, DT-capable, U-Boot
+ * bootloaders provided by Marvell. It is used in recent versions of
+ * DSM software provided by Synology. Nonetheless, some earlier boards
+ * were delivered with an older version of u-boot that left internal
+ * registers mapped at 0xd0000000. If you have such a device you will
+ * not be able to directly boot a kernel based on this Device Tree. In
+ * that case, the preferred solution is to update your bootloader (e.g.
+ * by upgrading to latest version of DSM, or building a new one and
+ * installing it from u-boot prompt) or adjust the Devive Tree
+ * (s/0xf1000000/0xd0000000/ in 'ranges' below).
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/gpio/gpio.h>
+#include "armada-xp-mv78230.dtsi"
+
+/ {
+	model = "Synology DS414";
+	compatible = "synology,ds414", "marvell,armadaxp-mv78230",
+		     "marvell,armadaxp", "marvell,armada-370-xp";
+
+	chosen {
+		bootargs = "console=ttyS0,115200 earlyprintk";
+		stdout-path = &uart0;
+	};
+
+	aliases {
+		spi0 = &spi0;
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0 0x00000000 0 0x40000000>; /* 1GB */
+	};
+
+	soc {
+		ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xf1000000 0x100000
+			  MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000>;
+
+		pcie-controller {
+			status = "okay";
+
+			/*
+			 * Connected to Marvell 88SX7042 SATA-II controller
+			 * handling the four disks.
+			 */
+			pcie@1,0 {
+				/* Port 0, Lane 0 */
+				status = "okay";
+			};
+
+			/*
+			 * Connected to EtronTech EJ168A XHCI controller
+			 * providing the two rear USB 3.0 ports.
+			 */
+			pcie@5,0 {
+				/* Port 1, Lane 0 */
+				status = "okay";
+			};
+		};
+
+		internal-regs {
+
+			/* RTC is provided by Seiko S-35390A below */
+			rtc@10300 {
+				status = "disabled";
+			};
+
+			spi0: spi@10600 {
+				status = "okay";
+				u-boot,dm-pre-reloc;
+
+				spi-flash@0 {
+					u-boot,dm-pre-reloc;
+					#address-cells = <1>;
+					#size-cells = <1>;
+					compatible = "micron,n25q064";
+					reg = <0>; /* Chip select 0 */
+					spi-max-frequency = <20000000>;
+
+					/*
+					 * Warning!
+					 *
+					 * Synology u-boot uses its compiled-in environment
+					 * and it seems Synology did not care to change u-boot
+					 * default configuration in order to allow saving a
+					 * modified environment at a sensible location. So,
+					 * if you do a 'saveenv' under u-boot, your modified
+					 * environment will be saved at 1MB after the start
+					 * of the flash, i.e. in the middle of the uImage.
+					 * For that reason, it is strongly advised not to
+					 * change the default environment, unless you know
+					 * what you are doing.
+					 */
+					partition@00000000 { /* u-boot */
+						label = "RedBoot";
+						reg = <0x00000000 0x000d0000>; /* 832KB */
+					};
+
+					partition@000c0000 { /* uImage */
+						label = "zImage";
+						reg = <0x000d0000 0x002d0000>; /* 2880KB */
+					};
+
+					partition@003a0000 { /* uInitramfs */
+						label = "rd.gz";
+						reg = <0x003a0000 0x00430000>; /* 4250KB */
+					};
+
+					partition@007d0000 { /* MAC address and serial number */
+						label = "vendor";
+						reg = <0x007d0000 0x00010000>; /* 64KB */
+					};
+
+					partition@007e0000 {
+						label = "RedBoot config";
+						reg = <0x007e0000 0x00010000>; /* 64KB */
+					};
+
+					partition@007f0000 {
+						label = "FIS directory";
+						reg = <0x007f0000 0x00010000>; /* 64KB */
+					};
+				};
+			};
+
+			i2c@11000 {
+				clock-frequency = <400000>;
+				status = "okay";
+
+				s35390a: s35390a@30 {
+					 compatible = "sii,s35390a";
+					 reg = <0x30>;
+				};
+			};
+
+			/* Connected to a header on device's PCB. This
+			 * provides the main console for the device.
+			 *
+			 * Warning: the device may not boot with a 3.3V
+			 * USB-serial converter connected when the power
+			 * button is pressed. The converter needs to be
+			 * connected a few seconds after pressing the
+			 * power button. This is possibly due to UART0_TXD
+			 * pin being sampled at reset (bit 0 of SAR).
+			 */
+			serial@12000 {
+				status = "okay";
+				u-boot,dm-pre-reloc;
+			};
+
+			/* Connected to a Microchip PIC16F883 for power control */
+			serial@12100 {
+				status = "okay";
+			};
+
+			poweroff@12100 {
+				compatible = "synology,power-off";
+				reg = <0x12100 0x100>;
+				clocks = <&coreclk 0>;
+			};
+
+			/* Front USB 2.0 port */
+			usb@50000 {
+				status = "okay";
+			};
+
+			mdio {
+				phy0: ethernet-phy@0 { /* Marvell 88E1512 */
+					reg = <0>;
+				};
+
+				phy1: ethernet-phy@1 { /* Marvell 88E1512 */
+					reg = <1>;
+				};
+			};
+
+			ethernet@70000 {
+				status = "okay";
+				pinctrl-0 = <&ge0_rgmii_pins>;
+				pinctrl-names = "default";
+				phy = <&phy1>;
+				phy-mode = "rgmii-id";
+			};
+
+			ethernet@74000 {
+				pinctrl-0 = <&ge1_rgmii_pins>;
+				pinctrl-names = "default";
+				status = "okay";
+				phy = <&phy0>;
+				phy-mode = "rgmii-id";
+			};
+		};
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		pinctrl-0 = <&sata1_pwr_pin &sata2_pwr_pin
+			     &sata3_pwr_pin &sata4_pwr_pin>;
+		pinctrl-names = "default";
+
+		sata1_regulator: sata1-regulator {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "SATA1 Power";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			startup-delay-us = <2000000>;
+			enable-active-high;
+			regulator-always-on;
+			regulator-boot-on;
+			gpio = <&gpio1 10 GPIO_ACTIVE_HIGH>;
+		};
+
+		sata2_regulator: sata2-regulator {
+			compatible = "regulator-fixed";
+			reg = <2>;
+			regulator-name = "SATA2 Power";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			startup-delay-us = <4000000>;
+			enable-active-high;
+			regulator-always-on;
+			regulator-boot-on;
+			gpio = <&gpio1 12 GPIO_ACTIVE_HIGH>;
+		};
+
+		sata3_regulator: sata3-regulator {
+			compatible = "regulator-fixed";
+			reg = <3>;
+			regulator-name = "SATA3 Power";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			startup-delay-us = <6000000>;
+			enable-active-high;
+			regulator-always-on;
+			regulator-boot-on;
+			gpio = <&gpio1 13 GPIO_ACTIVE_HIGH>;
+		};
+
+		sata4_regulator: sata4-regulator {
+			compatible = "regulator-fixed";
+			reg = <4>;
+			regulator-name = "SATA4 Power";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			startup-delay-us = <8000000>;
+			enable-active-high;
+			regulator-always-on;
+			regulator-boot-on;
+			gpio = <&gpio1 14 GPIO_ACTIVE_HIGH>;
+		};
+	};
+};
+
+&pinctrl {
+	sata1_pwr_pin: sata1-pwr-pin {
+		marvell,pins = "mpp42";
+		marvell,function = "gpio";
+	};
+
+	sata2_pwr_pin: sata2-pwr-pin {
+		marvell,pins = "mpp44";
+		marvell,function = "gpio";
+	};
+
+	sata3_pwr_pin: sata3-pwr-pin {
+		marvell,pins = "mpp45";
+		marvell,function = "gpio";
+	};
+
+	sata4_pwr_pin: sata4-pwr-pin {
+		marvell,pins = "mpp46";
+		marvell,function = "gpio";
+	};
+
+	sata1_pres_pin: sata1-pres-pin {
+		marvell,pins = "mpp34";
+		marvell,function = "gpio";
+	};
+
+	sata2_pres_pin: sata2-pres-pin {
+		marvell,pins = "mpp35";
+		marvell,function = "gpio";
+	};
+
+	sata3_pres_pin: sata3-pres-pin {
+		marvell,pins = "mpp40";
+		marvell,function = "gpio";
+	};
+
+	sata4_pres_pin: sata4-pres-pin {
+		marvell,pins = "mpp41";
+		marvell,function = "gpio";
+	};
+
+	syno_id_bit0_pin: syno-id-bit0-pin {
+		marvell,pins = "mpp26";
+		marvell,function = "gpio";
+	};
+
+	syno_id_bit1_pin: syno-id-bit1-pin {
+		marvell,pins = "mpp28";
+		marvell,function = "gpio";
+	};
+
+	syno_id_bit2_pin: syno-id-bit2-pin {
+		marvell,pins = "mpp29";
+		marvell,function = "gpio";
+	};
+
+	fan1_alarm_pin: fan1-alarm-pin {
+		marvell,pins = "mpp33";
+		marvell,function = "gpio";
+	};
+
+	fan2_alarm_pin: fan2-alarm-pin {
+		marvell,pins = "mpp32";
+		marvell,function = "gpio";
+	};
+};
diff --git a/arch/arm/dts/armada-xp.dtsi b/arch/arm/dts/armada-xp.dtsi
index 3de9b761cc1ab0fe7a8d3f0ea9caa7ca72e2a989..3fac39e41d789199947a3927bf7c4630ea14c275 100644
--- a/arch/arm/dts/armada-xp.dtsi
+++ b/arch/arm/dts/armada-xp.dtsi
@@ -63,6 +63,7 @@
 
 	soc {
 		compatible = "marvell,armadaxp-mbus", "simple-bus";
+		u-boot,dm-pre-reloc;
 
 		bootrom {
 			compatible = "marvell,bootrom";
diff --git a/arch/arm/mach-kirkwood/include/mach/config.h b/arch/arm/mach-kirkwood/include/mach/config.h
index d04939503635d9eb0795344646ecf4b986e39d4a..0c4309ff0078aea57302f0784d9c549f29ec3446 100644
--- a/arch/arm/mach-kirkwood/include/mach/config.h
+++ b/arch/arm/mach-kirkwood/include/mach/config.h
@@ -135,4 +135,9 @@
 #define CONFIG_SYS_I2C_SPEED		100000
 #endif
 
+/* Use common timer */
+#define CONFIG_SYS_TIMER_COUNTS_DOWN
+#define CONFIG_SYS_TIMER_COUNTER	(MVEBU_TIMER_BASE + 0x14)
+#define CONFIG_SYS_TIMER_RATE		CONFIG_SYS_TCLK
+
 #endif /* _KW_CONFIG_H */
diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
index 79ff0e82786db029a267458e125bbf9c11d26ec9..b9628462eab890e19e8d3725a30967a7a2f2c407 100644
--- a/arch/arm/mach-mvebu/Kconfig
+++ b/arch/arm/mach-mvebu/Kconfig
@@ -1,31 +1,74 @@
 if ARCH_MVEBU
 
+config ARMADA_38X
+	bool
+
+config ARMADA_XP
+	bool
+
+config MV78230
+	bool
+	select ARMADA_XP
+
+config MV78260
+	bool
+	select ARMADA_XP
+
+config MV78460
+	bool
+	select ARMADA_XP
+
+config DB_88F6820_GP
+	bool
+	select ARMADA_38X
+
 choice
 	prompt "Marvell MVEBU (Armada XP/38x) board select"
 	optional
 
+config TARGET_CLEARFOG
+	bool "Support ClearFog"
+	select DB_88F6820_GP
+
 config TARGET_DB_88F6820_GP
 	bool "Support DB-88F6820-GP"
+	select DB_88F6820_GP
 
 config TARGET_DB_MV784MP_GP
 	bool "Support db-mv784mp-gp"
+	select MV78460
+
+config TARGET_DS414
+	bool "Support Synology DS414"
+	select MV78230
 
 config TARGET_MAXBCM
 	bool "Support maxbcm"
+	select MV78460
 
 endchoice
 
-config SYS_SOC
-	default "mvebu"
+config SYS_BOARD
+	default "clearfog" if TARGET_CLEARFOG
+	default "db-88f6820-gp" if TARGET_DB_88F6820_GP
+	default "db-mv784mp-gp" if TARGET_DB_MV784MP_GP
+	default "ds414" if TARGET_DS414
+	default "maxbcm" if TARGET_MAXBCM
 
-config MVEBU_BOOTROM_UARTBOOT
-	bool "Use kwboot to boot via BootROM xmodem protocol"
-	help
-	  This option provides support for booting via the Marvell
-	  xmodem protocol, used by the kwboot tool.
+config SYS_CONFIG_NAME
+	default "clearfog" if TARGET_CLEARFOG
+	default "db-88f6820-gp" if TARGET_DB_88F6820_GP
+	default "db-mv784mp-gp" if TARGET_DB_MV784MP_GP
+	default "ds414" if TARGET_DS414
+	default "maxbcm" if TARGET_MAXBCM
 
-	  Please don't forget to configure the boot device in
-	  the board specific kwbimage.cfg file this way:
-	      BOOT_FROM uart
+config SYS_VENDOR
+	default "Marvell" if TARGET_DB_MV784MP_GP
+	default "Marvell" if TARGET_DB_88F6820_GP
+	default "solidrun" if TARGET_CLEARFOG
+	default "Synology" if TARGET_DS414
+
+config SYS_SOC
+	default "mvebu"
 
 endif
diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile
index 21c56a4d969889a054467a1cba134efac70edf20..b96b81bd3933eeb2a404a46a0d61146fc1094738 100644
--- a/arch/arm/mach-mvebu/Makefile
+++ b/arch/arm/mach-mvebu/Makefile
@@ -15,8 +15,8 @@ else
 obj-y	= cpu.o
 obj-y	+= dram.o
 ifndef CONFIG_SPL_BUILD
-obj-$(CONFIG_SYS_MVEBU_DDR_A38X) += ../../../drivers/ddr/marvell/a38x/xor.o
-obj-$(CONFIG_SYS_MVEBU_DDR_AXP) += ../../../drivers/ddr/marvell/axp/xor.o
+obj-$(CONFIG_ARMADA_38X) += ../../../drivers/ddr/marvell/a38x/xor.o
+obj-$(CONFIG_ARMADA_XP) += ../../../drivers/ddr/marvell/axp/xor.o
 endif
 obj-y	+= gpio.o
 obj-y	+= mbus.o
@@ -24,7 +24,7 @@ obj-y	+= timer.o
 obj-$(CONFIG_SPL_BUILD) += spl.o
 obj-$(CONFIG_SPL_BUILD) += lowlevel_spl.o
 
-obj-$(CONFIG_SYS_MVEBU_DDR_A38X) += serdes/a38x/
-obj-$(CONFIG_SYS_MVEBU_DDR_AXP)	+= serdes/axp/
+obj-$(CONFIG_ARMADA_38X) += serdes/a38x/
+obj-$(CONFIG_ARMADA_XP) += serdes/axp/
 
 endif
diff --git a/arch/arm/mach-mvebu/cpu.c b/arch/arm/mach-mvebu/cpu.c
index 895ad929b10721e4f1d28c0402efd71fc97ade42..30b175c64657111fcd536bb6a7bf80f0c7553490 100644
--- a/arch/arm/mach-mvebu/cpu.c
+++ b/arch/arm/mach-mvebu/cpu.c
@@ -1,11 +1,10 @@
 /*
- * Copyright (C) 2014-2015 Stefan Roese <sr@denx.de>
+ * Copyright (C) 2014-2016 Stefan Roese <sr@denx.de>
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
 #include <common.h>
-#include <netdev.h>
 #include <ahci.h>
 #include <linux/mbus.h>
 #include <asm/io.h>
@@ -50,25 +49,106 @@ int mvebu_soc_family(void)
 {
 	u16 devid = (readl(MVEBU_REG_PCIE_DEVID) >> 16) & 0xffff;
 
-	if (devid == SOC_MV78460_ID)
+	switch (devid) {
+	case SOC_MV78230_ID:
+	case SOC_MV78260_ID:
+	case SOC_MV78460_ID:
 		return MVEBU_SOC_AXP;
-
-	if (devid == SOC_88F6810_ID || devid == SOC_88F6820_ID ||
-	    devid == SOC_88F6828_ID)
+	case SOC_88F6810_ID:
+	case SOC_88F6820_ID:
+	case SOC_88F6828_ID:
 		return MVEBU_SOC_A38X;
-
+	}
 	return MVEBU_SOC_UNKNOWN;
 }
 
 #if defined(CONFIG_DISPLAY_CPUINFO)
+
+#if defined(CONFIG_ARMADA_38X)
+/* SAR frequency values for Armada 38x */
+static const struct sar_freq_modes sar_freq_tab[] = {
+	{  0x0,  0x0,  666, 333, 333 },
+	{  0x2,  0x0,  800, 400, 400 },
+	{  0x4,  0x0, 1066, 533, 533 },
+	{  0x6,  0x0, 1200, 600, 600 },
+	{  0x8,  0x0, 1332, 666, 666 },
+	{  0xc,  0x0, 1600, 800, 800 },
+	{ 0xff, 0xff,    0,   0,   0 }	/* 0xff marks end of array */
+};
+#else
+/* SAR frequency values for Armada XP */
+static const struct sar_freq_modes sar_freq_tab[] = {
+	{  0xa,  0x5,  800, 400, 400 },
+	{  0x1,  0x5, 1066, 533, 533 },
+	{  0x2,  0x5, 1200, 600, 600 },
+	{  0x2,  0x9, 1200, 600, 400 },
+	{  0x3,  0x5, 1333, 667, 667 },
+	{  0x4,  0x5, 1500, 750, 750 },
+	{  0x4,  0x9, 1500, 750, 500 },
+	{  0xb,  0x9, 1600, 800, 533 },
+	{  0xb,  0xa, 1600, 800, 640 },
+	{  0xb,  0x5, 1600, 800, 800 },
+	{ 0xff, 0xff,    0,   0,   0 }	/* 0xff marks end of array */
+};
+#endif
+
+void get_sar_freq(struct sar_freq_modes *sar_freq)
+{
+	u32 val;
+	u32 freq;
+	int i;
+
+	val = readl(CONFIG_SAR_REG);	/* SAR - Sample At Reset */
+	freq = (val & SAR_CPU_FREQ_MASK) >> SAR_CPU_FREQ_OFFS;
+#if !defined(CONFIG_ARMADA_38X)
+	/*
+	 * Shift CPU0 clock frequency select bit from SAR2 register
+	 * into correct position
+	 */
+	freq |= ((readl(CONFIG_SAR2_REG) & SAR2_CPU_FREQ_MASK)
+		 >> SAR2_CPU_FREQ_OFFS) << 3;
+#endif
+	for (i = 0; sar_freq_tab[i].val != 0xff; i++) {
+		if (sar_freq_tab[i].val == freq) {
+#if defined(CONFIG_ARMADA_38X)
+			*sar_freq = sar_freq_tab[i];
+			return;
+#else
+			int k;
+			u8 ffc;
+
+			ffc = (val & SAR_FFC_FREQ_MASK) >>
+				SAR_FFC_FREQ_OFFS;
+			for (k = i; sar_freq_tab[k].ffc != 0xff; k++) {
+				if (sar_freq_tab[k].ffc == ffc) {
+					*sar_freq = sar_freq_tab[k];
+					return;
+				}
+			}
+			i = k;
+#endif
+		}
+	}
+
+	/* SAR value not found, return 0 for frequencies */
+	*sar_freq = sar_freq_tab[i - 1];
+}
+
 int print_cpuinfo(void)
 {
 	u16 devid = (readl(MVEBU_REG_PCIE_DEVID) >> 16) & 0xffff;
 	u8 revid = readl(MVEBU_REG_PCIE_REVID) & 0xff;
+	struct sar_freq_modes sar_freq;
 
 	puts("SoC:   ");
 
 	switch (devid) {
+	case SOC_MV78230_ID:
+		puts("MV78230-");
+		break;
+	case SOC_MV78260_ID:
+		puts("MV78260-");
+		break;
 	case SOC_MV78460_ID:
 		puts("MV78460-");
 		break;
@@ -89,13 +169,13 @@ int print_cpuinfo(void)
 	if (mvebu_soc_family() == MVEBU_SOC_AXP) {
 		switch (revid) {
 		case 1:
-			puts("A0\n");
+			puts("A0");
 			break;
 		case 2:
-			puts("B0\n");
+			puts("B0");
 			break;
 		default:
-			printf("?? (%x)\n", revid);
+			printf("?? (%x)", revid);
 			break;
 		}
 	}
@@ -103,17 +183,20 @@ int print_cpuinfo(void)
 	if (mvebu_soc_family() == MVEBU_SOC_A38X) {
 		switch (revid) {
 		case MV_88F68XX_Z1_ID:
-			puts("Z1\n");
+			puts("Z1");
 			break;
 		case MV_88F68XX_A0_ID:
-			puts("A0\n");
+			puts("A0");
 			break;
 		default:
-			printf("?? (%x)\n", revid);
+			printf("?? (%x)", revid);
 			break;
 		}
 	}
 
+	get_sar_freq(&sar_freq);
+	printf(" at %d MHz\n", sar_freq.p_clk);
+
 	return 0;
 }
 #endif /* CONFIG_DISPLAY_CPUINFO */
@@ -199,10 +282,10 @@ static void setup_usb_phys(void)
 	clrsetbits_le32(MV_USB_PHY_PLL_REG(1), 0x3ff, 0x605);
 
 	/* Power up PLL and PHY channel */
-	clrsetbits_le32(MV_USB_PHY_PLL_REG(2), 0, BIT(9));
+	setbits_le32(MV_USB_PHY_PLL_REG(2), BIT(9));
 
 	/* Assert VCOCAL_START */
-	clrsetbits_le32(MV_USB_PHY_PLL_REG(1), 0, BIT(21));
+	setbits_le32(MV_USB_PHY_PLL_REG(1), BIT(21));
 
 	mdelay(1);
 
@@ -211,18 +294,20 @@ static void setup_usb_phys(void)
 	 */
 
 	for (dev = 0; dev < 3; dev++) {
-		clrsetbits_le32(MV_USB_X3_PHY_CHANNEL(dev, 3), 0, BIT(15));
+		setbits_le32(MV_USB_X3_PHY_CHANNEL(dev, 3), BIT(15));
 
 		/* Assert REG_RCAL_START in channel REG 1 */
-		clrsetbits_le32(MV_USB_X3_PHY_CHANNEL(dev, 1), 0, BIT(12));
+		setbits_le32(MV_USB_X3_PHY_CHANNEL(dev, 1), BIT(12));
 		udelay(40);
-		clrsetbits_le32(MV_USB_X3_PHY_CHANNEL(dev, 1), BIT(12), 0);
+		clrbits_le32(MV_USB_X3_PHY_CHANNEL(dev, 1), BIT(12));
 	}
 }
 
+/*
+ * This function is not called from the SPL U-Boot version
+ */
 int arch_cpu_init(void)
 {
-#if !defined(CONFIG_SPL_BUILD)
 	struct pl310_regs *const pl310 =
 		(struct pl310_regs *)CONFIG_SYS_PL310_BASE;
 
@@ -233,27 +318,26 @@ int arch_cpu_init(void)
 	 * still locked to cache.
 	 */
 	mmu_disable();
-#endif
 
 	/* Linux expects the internal registers to be at 0xf1000000 */
 	writel(SOC_REGS_PHY_BASE, INTREG_BASE_ADDR_REG);
 	set_cbar(SOC_REGS_PHY_BASE + 0xC000);
 
-#if !defined(CONFIG_SPL_BUILD)
 	/*
 	 * From this stage on, the SoC detection is working. As we have
 	 * configured the internal register base to the value used
 	 * in the macros / defines in the U-Boot header (soc.h).
 	 */
 
-	/*
-	 * To fully release / unlock this area from cache, we need
-	 * to flush all caches and disable the L2 cache.
-	 */
-	icache_disable();
-	dcache_disable();
-	clrbits_le32(&pl310->pl310_ctrl, L2X0_CTRL_EN);
-#endif
+	if (mvebu_soc_family() == MVEBU_SOC_A38X) {
+		/*
+		 * To fully release / unlock this area from cache, we need
+		 * to flush all caches and disable the L2 cache.
+		 */
+		icache_disable();
+		dcache_disable();
+		clrbits_le32(&pl310->pl310_ctrl, L2X0_CTRL_EN);
+	}
 
 	/*
 	 * We need to call mvebu_mbus_probe() before calling
@@ -326,30 +410,6 @@ int arch_misc_init(void)
 }
 #endif /* CONFIG_ARCH_MISC_INIT */
 
-#ifdef CONFIG_MVNETA
-int cpu_eth_init(bd_t *bis)
-{
-	u32 enet_base[] = { MVEBU_EGIGA0_BASE, MVEBU_EGIGA1_BASE,
-			    MVEBU_EGIGA2_BASE, MVEBU_EGIGA3_BASE };
-	u8 phy_addr[] = CONFIG_PHY_ADDR;
-	int i;
-
-	/*
-	 * Only Armada XP supports all 4 ethernet interfaces. A38x has
-	 * slightly different base addresses for its 2-3 interfaces.
-	 */
-	if (mvebu_soc_family() != MVEBU_SOC_AXP) {
-		enet_base[1] = MVEBU_EGIGA2_BASE;
-		enet_base[2] = MVEBU_EGIGA3_BASE;
-	}
-
-	for (i = 0; i < ARRAY_SIZE(phy_addr); i++)
-		mvneta_initialize(bis, enet_base[i], i, phy_addr[i]);
-
-	return 0;
-}
-#endif
-
 #ifdef CONFIG_MV_SDHCI
 int board_mmc_init(bd_t *bis)
 {
@@ -413,20 +473,43 @@ void scsi_init(void)
 }
 #endif
 
-#ifndef CONFIG_SYS_DCACHE_OFF
 void enable_caches(void)
 {
-	struct pl310_regs *const pl310 =
-		(struct pl310_regs *)CONFIG_SYS_PL310_BASE;
-
-	/* First disable L2 cache - may still be enable from BootROM */
-	if (mvebu_soc_family() == MVEBU_SOC_A38X)
-		clrbits_le32(&pl310->pl310_ctrl, L2X0_CTRL_EN);
-
 	/* Avoid problem with e.g. neta ethernet driver */
 	invalidate_dcache_all();
 
 	/* Enable D-cache. I-cache is already enabled in start.S */
 	dcache_enable();
 }
-#endif
+
+void v7_outer_cache_enable(void)
+{
+	if (mvebu_soc_family() == MVEBU_SOC_AXP) {
+		struct pl310_regs *const pl310 =
+			(struct pl310_regs *)CONFIG_SYS_PL310_BASE;
+		u32 u;
+
+		/* The L2 cache is already disabled at this point */
+
+		/*
+		 * For Aurora cache in no outer mode, enable via the CP15
+		 * coprocessor broadcasting of cache commands to L2.
+		 */
+		asm volatile("mrc p15, 1, %0, c15, c2, 0" : "=r" (u));
+		u |= BIT(8);		/* Set the FW bit */
+		asm volatile("mcr p15, 1, %0, c15, c2, 0" : : "r" (u));
+
+		isb();
+
+		/* Enable the L2 cache */
+		setbits_le32(&pl310->pl310_ctrl, L2X0_CTRL_EN);
+	}
+}
+
+void v7_outer_cache_disable(void)
+{
+	struct pl310_regs *const pl310 =
+		(struct pl310_regs *)CONFIG_SYS_PL310_BASE;
+
+	clrbits_le32(&pl310->pl310_ctrl, L2X0_CTRL_EN);
+}
diff --git a/arch/arm/mach-mvebu/dram.c b/arch/arm/mach-mvebu/dram.c
index ddc5b7ee3eaf5b49cf4dcd410f2cad3a826bc955..a8ec5ea21b6fe2e58a04be7b573ac0eef4e548b3 100644
--- a/arch/arm/mach-mvebu/dram.c
+++ b/arch/arm/mach-mvebu/dram.c
@@ -12,11 +12,8 @@
 #include <asm/arch/cpu.h>
 #include <asm/arch/soc.h>
 
-#ifdef CONFIG_SYS_MVEBU_DDR_A38X
-#include "../../../drivers/ddr/marvell/axp/xor.h"
-#include "../../../drivers/ddr/marvell/axp/xor_regs.h"
-#endif
-#ifdef CONFIG_SYS_MVEBU_DDR_AXP
+#if defined(CONFIG_ARCH_MVEBU)
+/* Use common XOR definitions for A3x and AXP */
 #include "../../../drivers/ddr/marvell/axp/xor.h"
 #include "../../../drivers/ddr/marvell/axp/xor_regs.h"
 #endif
@@ -112,7 +109,7 @@ void mvebu_sdram_size_adjust(enum memory_bank bank)
 	mvebu_sdram_bs_set(bank, size);
 }
 
-#if defined(CONFIG_SYS_MVEBU_DDR_A38X) || defined(CONFIG_SYS_MVEBU_DDR_AXP)
+#if defined(CONFIG_ARCH_MVEBU)
 static u32 xor_ctrl_save;
 static u32 xor_base_save;
 static u32 xor_mask_save;
@@ -292,11 +289,18 @@ void dram_init_banksize(void)
 	}
 }
 
+#if defined(CONFIG_ARCH_MVEBU)
 void board_add_ram_info(int use_default)
 {
+	struct sar_freq_modes sar_freq;
+
+	get_sar_freq(&sar_freq);
+	printf(" (%d MHz, ", sar_freq.d_clk);
+
 	if (ecc_enabled())
-		printf(" (ECC");
+		printf("ECC");
 	else
-		printf(" (ECC not");
+		printf("ECC not");
 	printf(" enabled)");
 }
+#endif
diff --git a/arch/arm/mach-mvebu/include/mach/config.h b/arch/arm/mach-mvebu/include/mach/config.h
index 1d49cab7fd89e431845357fbfc05d0c25fb5cebb..cc1fc5f9d4b1842141068095b5a668c97a0e3346 100644
--- a/arch/arm/mach-mvebu/include/mach/config.h
+++ b/arch/arm/mach-mvebu/include/mach/config.h
@@ -17,12 +17,22 @@
 
 #include <asm/arch/soc.h>
 
-#if defined(CONFIG_ARMADA_XP)
+#if defined(CONFIG_ARMADA_XP) || defined(CONFIG_ARMADA_38X)
+/*
+ * Set this for the common xor register definitions needed in dram.c
+ * for A38x as well here.
+ */
 #define MV88F78X60 /* for the DDR training bin_hdr code */
 #endif
 
 #define CONFIG_SYS_CACHELINE_SIZE	32
 
+#define CONFIG_SYS_L2_PL310
+
+#ifdef CONFIG_SPL_BUILD
+#define CONFIG_SKIP_LOWLEVEL_INIT	/* disable board lowlevel_init */
+#endif
+
 /*
  * By default kwbimage.cfg from board specific folder is used
  * If for some board, different configuration file need to be used,
@@ -47,8 +57,7 @@
  * SPI Flash configuration
  */
 #ifdef CONFIG_CMD_SF
-#define CONFIG_HARD_SPI			1
-#define CONFIG_KIRKWOOD_SPI		1
+#define CONFIG_KIRKWOOD_SPI
 #ifndef CONFIG_ENV_SPI_BUS
 # define CONFIG_ENV_SPI_BUS		0
 #endif
@@ -60,6 +69,9 @@
 #endif
 #endif
 
+/* Needed for SPI NOR booting in SPL */
+#define CONFIG_DM_SEQ_ALIAS		1
+
 /*
  * Ethernet Driver configuration
  */
@@ -85,9 +97,9 @@
 #define CONFIG_SYS_I2C_SPEED		100000
 #endif
 
-/* Common SPL configuration */
-#ifndef CONFIG_SPL_LDSCRIPT
-#define CONFIG_SPL_LDSCRIPT		"arch/arm/mach-mvebu/u-boot-spl.lds"
-#endif
+/* Use common timer */
+#define CONFIG_SYS_TIMER_COUNTS_DOWN
+#define CONFIG_SYS_TIMER_COUNTER	(MVEBU_TIMER_BASE + 0x14)
+#define CONFIG_SYS_TIMER_RATE		25000000
 
 #endif /* __MVEBU_CONFIG_H */
diff --git a/arch/arm/mach-mvebu/include/mach/cpu.h b/arch/arm/mach-mvebu/include/mach/cpu.h
index 5e8bf0c4ce0311704201ca942ee67b9d8514df41..47f45c1512a8686f3df1d729f5cc8ba196cdc202 100644
--- a/arch/arm/mach-mvebu/include/mach/cpu.h
+++ b/arch/arm/mach-mvebu/include/mach/cpu.h
@@ -106,6 +106,14 @@ struct kwgpio_registers {
 	u32 irq_level;
 };
 
+struct sar_freq_modes {
+	u8 val;
+	u8 ffc;		/* Fabric Frequency Configuration */
+	u32 p_clk;
+	u32 nb_clk;
+	u32 d_clk;
+};
+
 /* Needed for dynamic (board-specific) mbus configuration */
 extern struct mvebu_mbus_state mbus_state;
 
@@ -123,6 +131,8 @@ void return_to_bootrom(void);
 
 int mv_sdh_init(unsigned long regbase, u32 max_clk, u32 min_clk, u32 quirks);
 
+void get_sar_freq(struct sar_freq_modes *sar_freq);
+
 /*
  * Highspeed SERDES PHY config init, ported from bin_hdr
  * to mainline U-Boot
diff --git a/arch/arm/mach-mvebu/include/mach/soc.h b/arch/arm/mach-mvebu/include/mach/soc.h
index 22abde080e13fc1e8db0dd9c5fa3f04edf5835a0..cb216bc2cc61d5c2a14139d4538afcaefa43f70a 100644
--- a/arch/arm/mach-mvebu/include/mach/soc.h
+++ b/arch/arm/mach-mvebu/include/mach/soc.h
@@ -11,6 +11,8 @@
 #ifndef _MVEBU_SOC_H
 #define _MVEBU_SOC_H
 
+#define SOC_MV78230_ID		0x7823
+#define SOC_MV78260_ID		0x7826
 #define SOC_MV78460_ID		0x7846
 #define SOC_88F6810_ID		0x6810
 #define SOC_88F6820_ID		0x6820
@@ -33,10 +35,11 @@
 #define INTREG_BASE_ADDR_REG	(INTREG_BASE + 0x20080)
 #if defined(CONFIG_SPL_BUILD)
 /*
- * On A38x switching the regs base address without running from
- * SDRAM doesn't seem to work. So let the SPL still use the
- * default base address and switch to the new address in the
- * main u-boot later.
+ * The SPL U-Boot version still runs with the default
+ * address for the internal registers, configured by
+ * the BootROM. Only the main U-Boot version uses the
+ * new internal register base address, that also is
+ * required for the Linux kernel.
  */
 #define SOC_REGS_PHY_BASE	0xd0000000
 #else
@@ -47,10 +50,7 @@
 #define MVEBU_SDRAM_SCRATCH	(MVEBU_REGISTER(0x01504))
 #define MVEBU_L2_CACHE_BASE	(MVEBU_REGISTER(0x08000))
 #define CONFIG_SYS_PL310_BASE	MVEBU_L2_CACHE_BASE
-#define MVEBU_SPI_BASE		(MVEBU_REGISTER(0x10600))
 #define MVEBU_TWSI_BASE		(MVEBU_REGISTER(0x11000))
-#define MVEBU_UART0_BASE	(MVEBU_REGISTER(0x12000))
-#define MVEBU_UART1_BASE	(MVEBU_REGISTER(0x12100))
 #define MVEBU_MPP_BASE		(MVEBU_REGISTER(0x18000))
 #define MVEBU_GPIO0_BASE	(MVEBU_REGISTER(0x18100))
 #define MVEBU_GPIO1_BASE	(MVEBU_REGISTER(0x18140))
@@ -60,13 +60,9 @@
 #define MVEBU_CPU_WIN_BASE	(MVEBU_REGISTER(0x20000))
 #define MVEBU_SDRAM_BASE	(MVEBU_REGISTER(0x20180))
 #define MVEBU_TIMER_BASE	(MVEBU_REGISTER(0x20300))
-#define MVEBU_EGIGA2_BASE	(MVEBU_REGISTER(0x30000))
-#define MVEBU_EGIGA3_BASE	(MVEBU_REGISTER(0x34000))
 #define MVEBU_REG_PCIE_BASE	(MVEBU_REGISTER(0x40000))
 #define MVEBU_AXP_USB_BASE      (MVEBU_REGISTER(0x50000))
 #define MVEBU_USB20_BASE	(MVEBU_REGISTER(0x58000))
-#define MVEBU_EGIGA0_BASE	(MVEBU_REGISTER(0x70000))
-#define MVEBU_EGIGA1_BASE	(MVEBU_REGISTER(0x74000))
 #define MVEBU_AXP_SATA_BASE	(MVEBU_REGISTER(0xa0000))
 #define MVEBU_SATA0_BASE	(MVEBU_REGISTER(0xa8000))
 #define MVEBU_NAND_BASE		(MVEBU_REGISTER(0xd0000))
@@ -101,4 +97,49 @@
 #define MVCPU_WIN_ENABLE	CPU_WIN_ENABLE
 #define MVCPU_WIN_DISABLE	CPU_WIN_DISABLE
 
+#define COMPHY_REFCLK_ALIGNMENT	(MVEBU_REGISTER(0x182f8))
+
+/* BootROM error register (also includes some status infos) */
+#define CONFIG_BOOTROM_ERR_REG	(MVEBU_REGISTER(0x182d0))
+#define BOOTROM_ERR_MODE_OFFS	28
+#define BOOTROM_ERR_MODE_MASK	(0xf << BOOTROM_ERR_MODE_OFFS)
+#define BOOTROM_ERR_MODE_UART	0x6
+
+#if defined(CONFIG_ARMADA_38X)
+/* SAR values for Armada 38x */
+#define CONFIG_SAR_REG		(MVEBU_REGISTER(0x18600))
+
+#define SAR_CPU_FREQ_OFFS	10
+#define SAR_CPU_FREQ_MASK	(0x1f << SAR_CPU_FREQ_OFFS)
+#define SAR_BOOT_DEVICE_OFFS	4
+#define SAR_BOOT_DEVICE_MASK	(0x1f << SAR_BOOT_DEVICE_OFFS)
+
+#define BOOT_DEV_SEL_OFFS	4
+#define BOOT_DEV_SEL_MASK	(0x3f << BOOT_DEV_SEL_OFFS)
+
+#define BOOT_FROM_UART		0x28
+#define BOOT_FROM_SPI		0x32
+#define BOOT_FROM_MMC		0x30
+#define BOOT_FROM_MMC_ALT	0x31
+#else
+/* SAR values for Armada XP */
+#define CONFIG_SAR_REG		(MVEBU_REGISTER(0x18230))
+#define CONFIG_SAR2_REG		(MVEBU_REGISTER(0x18234))
+
+#define SAR_CPU_FREQ_OFFS	21
+#define SAR_CPU_FREQ_MASK	(0x7 << SAR_CPU_FREQ_OFFS)
+#define SAR_FFC_FREQ_OFFS	24
+#define SAR_FFC_FREQ_MASK	(0xf << SAR_FFC_FREQ_OFFS)
+#define SAR2_CPU_FREQ_OFFS	20
+#define SAR2_CPU_FREQ_MASK	(0x1 << SAR2_CPU_FREQ_OFFS)
+#define SAR_BOOT_DEVICE_OFFS	5
+#define SAR_BOOT_DEVICE_MASK	(0xf << SAR_BOOT_DEVICE_OFFS)
+
+#define BOOT_DEV_SEL_OFFS	5
+#define BOOT_DEV_SEL_MASK	(0xf << BOOT_DEV_SEL_OFFS)
+
+#define BOOT_FROM_UART		0x2
+#define BOOT_FROM_SPI		0x3
+#endif
+
 #endif /* _MVEBU_SOC_H */
diff --git a/arch/arm/mach-mvebu/lowlevel_spl.S b/arch/arm/mach-mvebu/lowlevel_spl.S
index 2e2181ecea5ebc2ad656772ff6056b9f43b42a6b..49e0b906d583f52ad89fe48b98bd639ec1480241 100644
--- a/arch/arm/mach-mvebu/lowlevel_spl.S
+++ b/arch/arm/mach-mvebu/lowlevel_spl.S
@@ -5,7 +5,6 @@
 #include <config.h>
 #include <linux/linkage.h>
 
-#ifdef CONFIG_MVEBU_BOOTROM_UARTBOOT
 ENTRY(save_boot_params)
 	stmfd	sp!, {r0 - r12, lr}	/* @ save registers on stack */
 	ldr	r12, =CONFIG_SPL_BOOTROM_SAVE
@@ -19,11 +18,6 @@ ENTRY(return_to_bootrom)
 	mov	r0, #0x0		/* @ return value: 0x0 NO_ERR */
 	ldmfd	sp!, {r0 - r12, pc}	/* @ restore regs and return */
 ENDPROC(return_to_bootrom)
-#else
-ENTRY(save_boot_params)
-	b	save_boot_params_ret
-ENDPROC(save_boot_params)
-#endif
 
 /*
  * cache_inv - invalidate Cache line
diff --git a/arch/arm/mach-mvebu/mbus.c b/arch/arm/mach-mvebu/mbus.c
index 346278e1beeb4919202b563686c908b1cea3c7ba..df263bc3b3997f5267fdd15822fcac1180ea6859 100644
--- a/arch/arm/mach-mvebu/mbus.c
+++ b/arch/arm/mach-mvebu/mbus.c
@@ -491,7 +491,7 @@ int mvebu_mbus_probe(struct mbus_win windows[], int count)
 #if defined(CONFIG_KIRKWOOD)
 	mbus_state.soc = &kirkwood_mbus_data;
 #endif
-#if defined(CONFIG_ARMADA_XP)
+#if defined(CONFIG_ARCH_MVEBU)
 	mbus_state.soc = &armada_370_xp_mbus_data;
 #endif
 
diff --git a/arch/arm/mach-mvebu/serdes/axp/board_env_spec.h b/arch/arm/mach-mvebu/serdes/axp/board_env_spec.h
index 36e0ed80f0d5aecc25b7227e3835ef893ed3d000..c8d9485b7bbba016250577f90d12aeae31f6d244 100644
--- a/arch/arm/mach-mvebu/serdes/axp/board_env_spec.h
+++ b/arch/arm/mach-mvebu/serdes/axp/board_env_spec.h
@@ -32,7 +32,7 @@
 #define BOARD_ID_BASE			0x0
 
 /* New board ID numbers */
-#define DB_88F78XX0_BP_ID		(BOARD_ID_BASE)
+#define DB_88F78XX0_BP_ID		(BOARD_ID_BASE + 1)
 #define RD_78460_SERVER_ID		(DB_88F78XX0_BP_ID + 1)
 #define DB_78X60_PCAC_ID		(RD_78460_SERVER_ID + 1)
 #define FPGA_88F78XX0_ID		(DB_78X60_PCAC_ID + 1)
@@ -44,7 +44,7 @@
 #define DB_784MP_GP_ID			(RD_78460_SERVER_REV2_ID + 1)
 #define RD_78460_CUSTOMER_ID		(DB_784MP_GP_ID + 1)
 #define MV_MAX_BOARD_ID			(RD_78460_CUSTOMER_ID + 1)
-#define INVALID_BAORD_ID		0xFFFFFFFF
+#define INVALID_BOARD_ID		0xFFFFFFFF
 
 /* Sample at Reset */
 #define MPP_SAMPLE_AT_RESET(id)		(0x18230 + (id * 4))
diff --git a/arch/arm/mach-mvebu/serdes/axp/high_speed_env_lib.c b/arch/arm/mach-mvebu/serdes/axp/high_speed_env_lib.c
index 702273aee128b28a0832c003112a639c80ee9424..afc0cefda3c17072fde24bc7896ce52f0987236b 100644
--- a/arch/arm/mach-mvebu/serdes/axp/high_speed_env_lib.c
+++ b/arch/arm/mach-mvebu/serdes/axp/high_speed_env_lib.c
@@ -75,16 +75,24 @@ static u32 board_id_get(void)
 #endif
 }
 
-static u8 board_sat_r_get(u8 dev_num, u8 reg)
+__weak u8 board_sat_r_get(u8 dev_num, u8 reg)
 {
 	u8 data;
 	u8 *dev;
 	u32 board_id = board_id_get();
 	int ret;
 
-	i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
-
 	switch (board_id) {
+	case DB_78X60_AMC_ID:
+	case DB_78X60_PCAC_REV2_ID:
+	case RD_78460_CUSTOMER_ID:
+	case RD_78460_SERVER_ID:
+	case RD_78460_SERVER_REV2_ID:
+	case DB_78X60_PCAC_ID:
+		return (0x1 << 1) | 1;
+	case FPGA_88F78XX0_ID:
+	case RD_78460_NAS_ID:
+		return (0x0 << 1) | 1;
 	case DB_784MP_GP_ID:
 		dev = rd78460gp_twsi_dev;
 
@@ -94,15 +102,12 @@ static u8 board_sat_r_get(u8 dev_num, u8 reg)
 		dev = db88f78xx0rev2_twsi_dev;
 		break;
 
-	case DB_78X60_PCAC_ID:
-	case FPGA_88F78XX0_ID:
-	case DB_78X60_PCAC_REV2_ID:
-	case RD_78460_SERVER_REV2_ID:
 	default:
 		return 0;
 	}
 
 	/* Read MPP module ID */
+	i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
 	ret = i2c_read(dev[dev_num], 0, 1, (u8 *)&data, 1);
 	if (ret)
 		return MV_ERROR;
@@ -190,8 +195,17 @@ __weak MV_BIN_SERDES_CFG *board_serdes_cfg_get(u8 pex_mode)
 
 u16 ctrl_model_get(void)
 {
-	/* Right now only MV78460 supported */
+	/*
+	 * SoC version can't be autodetected. So we need to rely on a define
+	 * from the config system here.
+	 */
+#if defined(CONFIG_MV78230)
+	return MV_78230_DEV_ID;
+#elif defined(CONFIG_MV78260)
+	return MV_78260_DEV_ID;
+#else
 	return MV_78460_DEV_ID;
+#endif
 }
 
 u32 get_line_cfg(u32 line_num, MV_BIN_SERDES_CFG *info)
@@ -202,6 +216,20 @@ u32 get_line_cfg(u32 line_num, MV_BIN_SERDES_CFG *info)
 		return (info->line8_15 >> ((line_num - 8) << 2)) & 0xF;
 }
 
+static int serdes_max_lines_get(void)
+{
+	switch (ctrl_model_get()) {
+	case MV_78230_DEV_ID:
+		return 7;
+	case MV_78260_DEV_ID:
+		return 12;
+	case MV_78460_DEV_ID:
+		return 16;
+	}
+
+	return 0;
+}
+
 int serdes_phy_config(void)
 {
 	int status = MV_OK;
@@ -221,39 +249,19 @@ int serdes_phy_config(void)
 	u8 device_rev;
 	u32 rx_high_imp_mode;
 	u16 ctrl_mode;
-	u32 board_id = board_id_get();
 	u32 pex_if;
 	u32 pex_if_num;
 
 	/*
-	 * TODO:
-	 * Right now we only support the MV78460 with 16 serdes lines
+	 * Get max. serdes lines count
 	 */
-	max_serdes_lines = 16;
+	max_serdes_lines = serdes_max_lines_get();
 	if (max_serdes_lines == 0)
 		return MV_OK;
 
-	switch (board_id) {
-	case DB_78X60_AMC_ID:
-	case DB_78X60_PCAC_REV2_ID:
-	case RD_78460_CUSTOMER_ID:
-	case RD_78460_SERVER_ID:
-	case RD_78460_SERVER_REV2_ID:
-	case DB_78X60_PCAC_ID:
-		satr11 = (0x1 << 1) | 1;
-		break;
-	case FPGA_88F78XX0_ID:
-	case RD_78460_NAS_ID:
-		satr11 = (0x0 << 1) | 1;
-		break;
-	case DB_88F78XX0_BP_REV2_ID:
-	case DB_784MP_GP_ID:
-	case DB_88F78XX0_BP_ID:
-		satr11 = board_sat_r_get(1, 1);
-		if ((u8) MV_ERROR == (u8) satr11)
-			return MV_ERROR;
-		break;
-	}
+	satr11 = board_sat_r_get(1, 1);
+	if ((u8) MV_ERROR == (u8) satr11)
+		return MV_ERROR;
 
 	board_modules_scan();
 	memset(addr, 0, sizeof(addr));
@@ -1356,19 +1364,19 @@ int serdes_phy_config(void)
 						 pex_if, PEX_DEVICE_AND_VENDOR_ID));
 			devId &= 0xFFFF;
 			devId |= ((ctrl_mode << 16) & 0xffff0000);
-			DEBUG_INIT_S("Update Device ID PEX");
-			DEBUG_INIT_D(pex_if, 1);
-			DEBUG_INIT_D(devId, 8);
-			DEBUG_INIT_S("\n");
+			DEBUG_INIT_FULL_S("Update Device ID PEX");
+			DEBUG_INIT_FULL_D(pex_if, 1);
+			DEBUG_INIT_FULL_D(devId, 8);
+			DEBUG_INIT_FULL_S("\n");
 			reg_write(PEX_CFG_DIRECT_ACCESS
 				  (pex_if, PEX_DEVICE_AND_VENDOR_ID), devId);
 			if ((pex_if < 8) &&
 			    (info->pex_mode[pex_unit] == PEX_BUS_MODE_X4))
 				pex_if += 3;
 		}
-		DEBUG_INIT_S("Update PEX Device ID 0x");
-		DEBUG_INIT_D(ctrl_mode, 4);
-		DEBUG_INIT_S("0\n");
+		DEBUG_INIT_FULL_S("Update PEX Device ID 0x");
+		DEBUG_INIT_FULL_D(ctrl_mode, 4);
+		DEBUG_INIT_FULL_S("0\n");
 	}
 	tmp = reg_read(PEX_DBG_STATUS_REG(0));
 	DEBUG_RD_REG(PEX_DBG_STATUS_REG(0), tmp);
diff --git a/arch/arm/mach-mvebu/spl.c b/arch/arm/mach-mvebu/spl.c
index 0ab729aa5d87ca3cc0dcefa2532ffdaff2622e55..0879873b9725828c2fd5e4b20437de0f2d102b8a 100644
--- a/arch/arm/mach-mvebu/spl.c
+++ b/arch/arm/mach-mvebu/spl.c
@@ -1,10 +1,13 @@
 /*
- * Copyright (C) 2014 Stefan Roese <sr@denx.de>
+ * Copyright (C) 2014-2016 Stefan Roese <sr@denx.de>
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
 #include <common.h>
+#include <dm.h>
+#include <debug_uart.h>
+#include <fdtdec.h>
 #include <spl.h>
 #include <asm/io.h>
 #include <asm/arch/cpu.h>
@@ -12,14 +15,45 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-u32 spl_boot_device(void)
+static u32 get_boot_device(void)
 {
-#if defined(CONFIG_SPL_SPI_FLASH_SUPPORT)
-	return BOOT_DEVICE_SPI;
-#endif
-#if defined(CONFIG_SPL_MMC_SUPPORT)
-	return BOOT_DEVICE_MMC1;
+	u32 val;
+	u32 boot_device;
+
+	/*
+	 * First check, if UART boot-mode is active. This can only
+	 * be done, via the bootrom error register. Here the
+	 * MSB marks if the UART mode is active.
+	 */
+	val = readl(CONFIG_BOOTROM_ERR_REG);
+	boot_device = (val & BOOTROM_ERR_MODE_MASK) >> BOOTROM_ERR_MODE_OFFS;
+	debug("BOOTROM_REG=0x%08x boot_device=0x%x\n", val, boot_device);
+	if (boot_device == BOOTROM_ERR_MODE_UART)
+		return BOOT_DEVICE_UART;
+
+	/*
+	 * Now check the SAR register for the strapped boot-device
+	 */
+	val = readl(CONFIG_SAR_REG);	/* SAR - Sample At Reset */
+	boot_device = (val & BOOT_DEV_SEL_MASK) >> BOOT_DEV_SEL_OFFS;
+	debug("SAR_REG=0x%08x boot_device=0x%x\n", val, boot_device);
+	switch (boot_device) {
+#ifdef CONFIG_SPL_MMC_SUPPORT
+	case BOOT_FROM_MMC:
+	case BOOT_FROM_MMC_ALT:
+		return BOOT_DEVICE_MMC1;
 #endif
+	case BOOT_FROM_UART:
+		return BOOT_DEVICE_UART;
+	case BOOT_FROM_SPI:
+	default:
+		return BOOT_DEVICE_SPI;
+	};
+}
+
+u32 spl_boot_device(void)
+{
+	return get_boot_device();
 }
 
 #ifdef CONFIG_SPL_MMC_SUPPORT
@@ -31,18 +65,7 @@ u32 spl_boot_mode(void)
 
 void board_init_f(ulong dummy)
 {
-#ifndef CONFIG_MVEBU_BOOTROM_UARTBOOT
-	/*
-	 * Only call arch_cpu_init() when not returning to the
-	 * Marvell BootROM, which is done when booting via
-	 * the xmodem protocol (kwboot tool). Otherwise the
-	 * internal register will get remapped and the BootROM
-	 * can't continue to run correctly.
-	 */
-
-	/* Linux expects the internal registers to be at 0xf1000000 */
-	arch_cpu_init();
-#endif
+	int ret;
 
 	/*
 	 * Pin muxing needs to be done before UART output, since
@@ -51,6 +74,27 @@ void board_init_f(ulong dummy)
 	 */
 	board_early_init_f();
 
+	/* Example code showing how to enable the debug UART on MVEBU */
+#ifdef EARLY_UART
+	/*
+	 * Debug UART can be used from here if required:
+	 *
+	 * debug_uart_init();
+	 * printch('a');
+	 * printhex8(0x1234);
+	 * printascii("string");
+	 */
+#endif
+
+	ret = spl_init();
+	if (ret) {
+		debug("spl_init() failed: %d\n", ret);
+		hang();
+	}
+
+	/* Use special translation offset for SPL */
+	dm_set_translation_offset(0xd0000000 - 0xf1000000);
+
 	preloader_console_init();
 
 	timer_init();
@@ -61,7 +105,6 @@ void board_init_f(ulong dummy)
 	/* Setup DDR */
 	ddr3_init();
 
-#ifdef CONFIG_MVEBU_BOOTROM_UARTBOOT
 	/*
 	 * Return to the BootROM to continue the Marvell xmodem
 	 * UART boot protocol. As initiated by the kwboot tool.
@@ -73,6 +116,6 @@ void board_init_f(ulong dummy)
 	 * need to return to the BootROM to enable this xmodem
 	 * UART download.
 	 */
-	return_to_bootrom();
-#endif
+	if (get_boot_device() == BOOT_DEVICE_UART)
+		return_to_bootrom();
 }
diff --git a/arch/arm/mach-mvebu/timer.c b/arch/arm/mach-mvebu/timer.c
index 5449a8926c5d2491824a300ed31e27e8596c4352..f5c2eaa808a3a0ccf7c0fbf22e06a4204d3908df 100644
--- a/arch/arm/mach-mvebu/timer.c
+++ b/arch/arm/mach-mvebu/timer.c
@@ -2,6 +2,8 @@
  * Copyright (C) Marvell International Ltd. and its affiliates
  * Written-by: Prafulla Wadaskar <prafulla@marvell.com>
  *
+ * Copyright (C) 2015 Stefan Roese <sr@denx.de>
+ *
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
@@ -9,108 +11,14 @@
 #include <asm/io.h>
 #include <asm/arch/soc.h>
 
-#define UBOOT_CNTR	0	/* counter to use for U-Boot timer */
-
-/*
- * ARM Timers Registers Map
- */
-#define CNTMR_CTRL_REG			&tmr_regs->ctrl
-#define CNTMR_RELOAD_REG(tmrnum)	&tmr_regs->tmr[tmrnum].reload
-#define CNTMR_VAL_REG(tmrnum)		&tmr_regs->tmr[tmrnum].val
-
-/*
- * ARM Timers Control Register
- * CPU_TIMERS_CTRL_REG (CTCR)
- */
-#define CTCR_ARM_TIMER_EN_OFFS(cntr)	(cntr * 2)
-#define CTCR_ARM_TIMER_EN(cntr)		(1 << CTCR_ARM_TIMER_EN_OFFS(cntr))
-
-#define CTCR_ARM_TIMER_AUTO_OFFS(cntr)	((cntr * 2) + 1)
-#define CTCR_ARM_TIMER_AUTO_EN(cntr)	(1 << CTCR_ARM_TIMER_AUTO_OFFS(cntr))
-
-/* Only Armada XP have the 25MHz enable bit (Kirkwood doesn't) */
-#if defined(CONFIG_ARMADA_XP)
-#define CTCR_ARM_TIMER_25MHZ_OFFS(cntr)	(cntr + 11)
-#define CTCR_ARM_TIMER_25MHZ(cntr)	(1 << CTCR_ARM_TIMER_25MHZ_OFFS(cntr))
-#else
-#define CTCR_ARM_TIMER_25MHZ(cntr)	0
-#endif
-
-#define TIMER_LOAD_VAL 			0xffffffff
-
-#define timestamp			gd->arch.tbl
-#define lastdec				gd->arch.lastinc
-
-static int init_done __attribute__((section(".data"))) = 0;
-
-/* Timer reload and current value registers */
-struct kwtmr_val {
-	u32 reload;	/* Timer reload reg */
-	u32 val;	/* Timer value reg */
-};
-
-/* Timer registers */
-struct kwtmr_registers {
-	u32 ctrl;	/* Timer control reg */
-	u32 pad[3];
-	struct kwtmr_val tmr[4];
-	u32 wdt_reload;
-	u32 wdt_val;
-};
-
 DECLARE_GLOBAL_DATA_PTR;
 
-static struct kwtmr_registers *tmr_regs =
-	(struct kwtmr_registers *)MVEBU_TIMER_BASE;
-
-static inline ulong read_timer(void)
-{
-	return readl(CNTMR_VAL_REG(UBOOT_CNTR))	/ (CONFIG_SYS_TCLK / 1000);
-}
-
-ulong get_timer_masked(void)
-{
-	ulong now = read_timer();
-
-	if (lastdec >= now) {
-		/* normal mode */
-		timestamp += lastdec - now;
-	} else {
-		/* we have an overflow ... */
-		timestamp += lastdec +
-			(TIMER_LOAD_VAL / (CONFIG_SYS_TCLK / 1000)) - now;
-	}
-	lastdec = now;
+#define TIMER_LOAD_VAL			0xffffffff
 
-	return timestamp;
-}
-
-ulong get_timer(ulong base)
-{
-	return get_timer_masked() - base;
-}
-
-void __udelay(unsigned long usec)
-{
-	uint current;
-	ulong delayticks;
-
-	current = readl(CNTMR_VAL_REG(UBOOT_CNTR));
-	delayticks = (usec * (CONFIG_SYS_TCLK / 1000000));
-
-	if (current < delayticks) {
-		delayticks -= current;
-		while (readl(CNTMR_VAL_REG(UBOOT_CNTR)) < current) ;
-		while ((TIMER_LOAD_VAL - delayticks) <
-			readl(CNTMR_VAL_REG(UBOOT_CNTR))) ;
-	} else {
-		while (readl(CNTMR_VAL_REG(UBOOT_CNTR)) >
-			(current - delayticks)) ;
-	}
-}
+static int init_done __attribute__((section(".data"))) = 0;
 
 /*
- * init the counter
+ * Timer initialization
  */
 int timer_init(void)
 {
@@ -120,35 +28,15 @@ int timer_init(void)
 	init_done = 1;
 
 	/* load value into timer */
-	writel(TIMER_LOAD_VAL, CNTMR_RELOAD_REG(UBOOT_CNTR));
-	writel(TIMER_LOAD_VAL, CNTMR_VAL_REG(UBOOT_CNTR));
+	writel(TIMER_LOAD_VAL, MVEBU_TIMER_BASE + 0x10);
+	writel(TIMER_LOAD_VAL, MVEBU_TIMER_BASE + 0x14);
 
+#if defined(CONFIG_ARCH_MVEBU)
+	/* On Armada XP / 38x ..., the 25MHz clock source needs to be enabled */
+	setbits_le32(MVEBU_TIMER_BASE + 0x00, BIT(11));
+#endif
 	/* enable timer in auto reload mode */
-	clrsetbits_le32(CNTMR_CTRL_REG, CTCR_ARM_TIMER_25MHZ(UBOOT_CNTR),
-			CTCR_ARM_TIMER_EN(UBOOT_CNTR) |
-			CTCR_ARM_TIMER_AUTO_EN(UBOOT_CNTR));
-
-	/* init the timestamp and lastdec value */
-	lastdec = read_timer();
-	timestamp = 0;
+	setbits_le32(MVEBU_TIMER_BASE + 0x00, 0x3);
 
 	return 0;
 }
-
-/*
- * This function is derived from PowerPC code (read timebase as long long).
- * On ARM it just returns the timer value.
- */
-unsigned long long get_ticks(void)
-{
-	return get_timer(0);
-}
-
-/*
- * This function is derived from PowerPC code (timebase clock frequency).
- * On ARM it returns the number of timer ticks per second.
- */
-ulong get_tbclk (void)
-{
-	return (ulong)CONFIG_SYS_HZ;
-}
diff --git a/arch/arm/mach-mvebu/u-boot-spl.lds b/arch/arm/mach-mvebu/u-boot-spl.lds
deleted file mode 100644
index eee1db49eedbfe54ddcb668f33365ec7d16be9a0..0000000000000000000000000000000000000000
--- a/arch/arm/mach-mvebu/u-boot-spl.lds
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * (C) Copyright 2002
- * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
- *
- * (C) Copyright 2010
- * Texas Instruments, <www.ti.com>
- *	Aneesh V <aneesh@ti.com>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-MEMORY { .sram : ORIGIN = CONFIG_SPL_TEXT_BASE,\
-		LENGTH = CONFIG_SPL_MAX_SIZE }
-MEMORY { .sdram : ORIGIN = CONFIG_SPL_BSS_START_ADDR, \
-		LENGTH = CONFIG_SPL_BSS_MAX_SIZE }
-
-OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
-OUTPUT_ARCH(arm)
-ENTRY(_start)
-SECTIONS
-{
-	.text      :
-	{
-		__start = .;
-		arch/arm/cpu/armv7/start.o	(.text*)
-		*(.text*)
-		*(.vectors)
-	} >.sram
-
-	. = ALIGN(4);
-	.rodata : { *(SORT_BY_ALIGNMENT(.rodata*)) } >.sram
-
-	. = ALIGN(4);
-	.data : { *(SORT_BY_ALIGNMENT(.data*)) } >.sram
-
-	. = ALIGN(4);
-	.u_boot_list : {
-		KEEP(*(SORT(.u_boot_list*_i2c_*)));
-	} >.sram
-
-	. = ALIGN(4);
-	__image_copy_end = .;
-
-	.end :
-	{
-		*(.__end)
-	}
-
-	.bss :
-	{
-		. = ALIGN(4);
-		__bss_start = .;
-		*(.bss*)
-		. = ALIGN(4);
-		__bss_end = .;
-	} >.sdram
-}
diff --git a/arch/arm/mvebu-common/Makefile b/arch/arm/mvebu-common/Makefile
deleted file mode 100644
index de243feaab51e1a2c86b4ebb15b5f8c5ef55d8fc..0000000000000000000000000000000000000000
--- a/arch/arm/mvebu-common/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-#
-# (C) Copyright 2009
-# Marvell Semiconductor <www.marvell.com>
-# Written-by: Prafulla Wadaskar <prafulla@marvell.com>
-#
-# SPDX-License-Identifier:	GPL-2.0+
-#
-
-obj-y	= dram.o
-obj-y	+= gpio.o
-obj-$(CONFIG_ARMADA_XP) += mbus.o
-obj-y	+= timer.o
-
-obj-y	+= serdes/
diff --git a/board/Marvell/db-88f6820-gp/Kconfig b/board/Marvell/db-88f6820-gp/Kconfig
deleted file mode 100644
index f12b96829df881c0abade4504f05e5e68ac00f6f..0000000000000000000000000000000000000000
--- a/board/Marvell/db-88f6820-gp/Kconfig
+++ /dev/null
@@ -1,12 +0,0 @@
-if TARGET_DB_88F6820_GP
-
-config SYS_BOARD
-	default "db-88f6820-gp"
-
-config SYS_VENDOR
-	default "Marvell"
-
-config SYS_CONFIG_NAME
-	default "db-88f6820-gp"
-
-endif
diff --git a/board/Marvell/db-88f6820-gp/kwbimage.cfg b/board/Marvell/db-88f6820-gp/kwbimage.cfg
index cc057925566c584d66b0dc73207f5a62523ad2f6..1f748db37c1e5b5b3d160a2f8fa8e7aed200a163 100644
--- a/board/Marvell/db-88f6820-gp/kwbimage.cfg
+++ b/board/Marvell/db-88f6820-gp/kwbimage.cfg
@@ -9,4 +9,4 @@ VERSION		1
 BOOT_FROM	spi
 
 # Binary Header (bin_hdr) with DDR3 training code
-BINARY spl/u-boot-spl.bin 0000005b 00000068
+BINARY spl/u-boot-spl-dtb.bin 0000005b 00000068
diff --git a/board/Marvell/db-mv784mp-gp/Kconfig b/board/Marvell/db-mv784mp-gp/Kconfig
deleted file mode 100644
index 428a5e15161fc2ff3c87834443c47f0f1989ca83..0000000000000000000000000000000000000000
--- a/board/Marvell/db-mv784mp-gp/Kconfig
+++ /dev/null
@@ -1,12 +0,0 @@
-if TARGET_DB_MV784MP_GP
-
-config SYS_BOARD
-	default "db-mv784mp-gp"
-
-config SYS_VENDOR
-	default "Marvell"
-
-config SYS_CONFIG_NAME
-	default "db-mv784mp-gp"
-
-endif
diff --git a/board/Marvell/db-mv784mp-gp/db-mv784mp-gp.c b/board/Marvell/db-mv784mp-gp/db-mv784mp-gp.c
index d7aa1499adf00aa6484107d8d9c6f7c70ebd2a9c..93052841170eb77b99e2f3646d8769d9741f8ca1 100644
--- a/board/Marvell/db-mv784mp-gp/db-mv784mp-gp.c
+++ b/board/Marvell/db-mv784mp-gp/db-mv784mp-gp.c
@@ -87,40 +87,32 @@ int board_eth_init(bd_t *bis)
 	return pci_eth_init(bis);
 }
 
-#ifdef CONFIG_RESET_PHY_R
-/* Configure and enable MV88E1545 PHY */
-void reset_phy(void)
+int board_phy_config(struct phy_device *phydev)
 {
-	u8 phy_addr[] = CONFIG_PHY_ADDR;
-	u16 devadr = phy_addr[0];
-	char *name = "neta0";
 	u16 reg;
 
-	if (miiphy_set_current_dev(name))
-		return;
-
 	/* Enable QSGMII AN */
 	/* Set page to 4 */
-	miiphy_write(name, devadr, 0x16, 4);
+	phy_write(phydev, MDIO_DEVAD_NONE, 0x16, 4);
 	/* Enable AN */
-	miiphy_write(name, devadr, 0x0, 0x1140);
+	phy_write(phydev, MDIO_DEVAD_NONE, 0x0, 0x1140);
 	/* Set page to 0 */
-	miiphy_write(name, devadr, 0x16, 0);
+	phy_write(phydev, MDIO_DEVAD_NONE, 0x16, 0);
 
 	/* Phy C_ANEG */
-	miiphy_read(name, devadr, 0x4, &reg);
+	reg = phy_read(phydev, MDIO_DEVAD_NONE, 0x4);
 	reg |= 0x1E0;
-	miiphy_write(name, devadr, 0x4, reg);
+	phy_write(phydev, MDIO_DEVAD_NONE, 0x4, reg);
 
 	/* Soft-Reset */
-	miiphy_write(name, devadr, 22, 0x0000);
-	miiphy_write(name, devadr, 0, 0x9140);
+	phy_write(phydev, MDIO_DEVAD_NONE, 22, 0x0000);
+	phy_write(phydev, MDIO_DEVAD_NONE, 0, 0x9140);
 
 	/* Power up the phy */
-	miiphy_read(name, devadr, ETH_PHY_CTRL_REG, &reg);
+	reg = phy_read(phydev, MDIO_DEVAD_NONE, ETH_PHY_CTRL_REG);
 	reg &= ~(ETH_PHY_CTRL_POWER_DOWN_MASK);
-	miiphy_write(name, devadr, ETH_PHY_CTRL_REG, reg);
+	phy_write(phydev, MDIO_DEVAD_NONE, ETH_PHY_CTRL_REG, reg);
 
-	printf("88E1545 Initialized on %s\n", name);
+	printf("88E1545 Initialized\n");
+	return 0;
 }
-#endif /* CONFIG_RESET_PHY_R */
diff --git a/board/Marvell/db-mv784mp-gp/kwbimage.cfg b/board/Marvell/db-mv784mp-gp/kwbimage.cfg
index cc057925566c584d66b0dc73207f5a62523ad2f6..1f748db37c1e5b5b3d160a2f8fa8e7aed200a163 100644
--- a/board/Marvell/db-mv784mp-gp/kwbimage.cfg
+++ b/board/Marvell/db-mv784mp-gp/kwbimage.cfg
@@ -9,4 +9,4 @@ VERSION		1
 BOOT_FROM	spi
 
 # Binary Header (bin_hdr) with DDR3 training code
-BINARY spl/u-boot-spl.bin 0000005b 00000068
+BINARY spl/u-boot-spl-dtb.bin 0000005b 00000068
diff --git a/board/Synology/common/Makefile b/board/Synology/common/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..e66aeb8467449bfd3e4ca71574f14e37864f49c0
--- /dev/null
+++ b/board/Synology/common/Makefile
@@ -0,0 +1,7 @@
+#
+# Copyright (C) 2015 Phil Sutter <phil@nwl.cc>
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y :=	cmd_syno.o
diff --git a/board/Synology/common/cmd_syno.c b/board/Synology/common/cmd_syno.c
new file mode 100644
index 0000000000000000000000000000000000000000..20544e29c45325985f8a4e396891213ded37d533
--- /dev/null
+++ b/board/Synology/common/cmd_syno.c
@@ -0,0 +1,227 @@
+/*
+ * Commands to deal with Synology specifics.
+ *
+ * Copyright (C) 2015  Phil Sutter <phil@nwl.cc>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <div64.h>
+#include <spi.h>
+#include <spi_flash.h>
+#include <linux/mtd/mtd.h>
+
+#include <asm/io.h>
+#include "../drivers/ddr/marvell/axp/ddr3_init.h"
+
+#define ETH_ALEN		6
+#define ETHADDR_MAX		4
+#define SYNO_SN_TAG		"SN="
+#define SYNO_CHKSUM_TAG		"CHK="
+
+
+static int do_syno_populate(int argc, char * const argv[])
+{
+	unsigned int bus = CONFIG_SF_DEFAULT_BUS;
+	unsigned int cs = CONFIG_SF_DEFAULT_CS;
+	unsigned int speed = CONFIG_SF_DEFAULT_SPEED;
+	unsigned int mode = CONFIG_SF_DEFAULT_MODE;
+	struct spi_flash *flash;
+	unsigned long addr = 0x80000; /* XXX: parameterize this? */
+	loff_t offset = 0x007d0000;
+	loff_t len = 0x00010000;
+	char *buf, *bufp;
+	char var[128];
+	char val[128];
+	int ret, n;
+
+	/* XXX: arg parsing to select flash here? */
+
+	flash = spi_flash_probe(bus, cs, speed, mode);
+	if (!flash) {
+		printf("Failed to initialize SPI flash at %u:%u\n", bus, cs);
+		return 1;
+	}
+
+	buf = map_physmem(addr, len, MAP_WRBACK);
+	if (!buf) {
+		puts("Failed to map physical memory\n");
+		return 1;
+	}
+
+	ret = spi_flash_read(flash, offset, len, buf);
+	if (ret) {
+		puts("Failed to read from SPI flash\n");
+		goto out_unmap;
+	}
+
+	for (n = 0; n < ETHADDR_MAX; n++) {
+		char ethaddr[ETH_ALEN];
+		int i, sum = 0;
+		unsigned char csum = 0;
+
+		for (i = 0, bufp = buf + n * 7; i < ETH_ALEN; i++) {
+			sum += bufp[i];
+			csum += bufp[i];
+			ethaddr[i] = bufp[i];
+		}
+		if (!sum)		/* MAC address empty */
+			continue;
+		if (csum != bufp[i]) {	/* seventh byte is checksum value */
+			printf("Invalid MAC address for interface %d!\n", n);
+			continue;
+		}
+		if (n == 0)
+			sprintf(var, "ethaddr");
+		else
+			sprintf(var, "eth%daddr", n);
+		snprintf(val, sizeof(val) - 1,
+		         "%02x:%02x:%02x:%02x:%02x:%02x",
+		         ethaddr[0], ethaddr[1], ethaddr[2],
+			 ethaddr[3], ethaddr[4], ethaddr[5]);
+		printf("parsed %s = %s\n", var, val);
+		setenv(var, val);
+	}
+	if (!strncmp(buf + 32, SYNO_SN_TAG, strlen(SYNO_SN_TAG))) {
+		char *snp, *csump;
+		int csum = 0;
+		unsigned long c;
+
+		snp = bufp = buf + 32 + strlen(SYNO_SN_TAG);
+		for (n = 0; bufp[n] && bufp[n] != ','; n++)
+			csum += bufp[n];
+		bufp[n] = '\0';
+
+		/* should come right after, but you never know */
+		bufp = strstr(bufp + n + 1, SYNO_CHKSUM_TAG);
+		if (!bufp) {
+			printf("Serial number checksum tag missing!\n");
+			goto out_unmap;
+		}
+
+		csump = bufp += strlen(SYNO_CHKSUM_TAG);
+		for (n = 0; bufp[n] && bufp[n] != ','; n++)
+			;
+		bufp[n] = '\0';
+
+		if (strict_strtoul(csump, 10, &c) || c != csum) {
+			puts("Invalid serial number found!\n");
+			ret = 1;
+			goto out_unmap;
+		}
+		printf("parsed SN = %s\n", snp);
+		setenv("SN", snp);
+	} else {	/* old style format */
+		unsigned char csum = 0;
+
+		for (n = 0, bufp = buf + 32; n < 10; n++)
+			csum += bufp[n];
+
+		if (csum != bufp[n]) {
+			puts("Invalid serial number found!\n");
+			ret = 1;
+			goto out_unmap;
+		}
+		bufp[n] = '\0';
+		printf("parsed SN = %s\n", buf + 32);
+		setenv("SN", buf + 32);
+	}
+out_unmap:
+	unmap_physmem(buf, len);
+	return ret;
+}
+
+/* map bit position to function in POWER_MNG_CTRL_REG */
+static const char * const pwr_mng_bit_func[] = {
+	"audio",
+	"ge3", "ge2", "ge1", "ge0",
+	"pcie00", "pcie01", "pcie02", "pcie03",
+	"pcie10", "pcie11", "pcie12", "pcie13",
+	"bp",
+	"sata0_link", "sata0_core",
+	"lcd",
+	"sdio",
+	"usb0", "usb1", "usb2",
+	"idma", "xor0", "crypto",
+	NULL,
+	"tdm",
+	"pcie20", "pcie30",
+	"xor1",
+	"sata1_link", "sata1_core",
+	NULL,
+};
+
+static int do_syno_clk_gate(int argc, char * const argv[])
+{
+	u32 pwr_mng_ctrl_reg = reg_read(POWER_MNG_CTRL_REG);
+	const char *func, *state;
+	int i, val;
+
+	if (argc < 2)
+		return -1;
+
+	if (!strcmp(argv[1], "get")) {
+		puts("Clock Gating:\n");
+		for (i = 0; i < 32; i++) {
+			func = pwr_mng_bit_func[i];
+			if (!func)
+				continue;
+			state = pwr_mng_ctrl_reg & (1 << i) ?  "ON" : "OFF";
+			printf("%s:\t\t%s\n", func, state);
+		}
+		return 0;
+	}
+	if (argc < 4)
+		return -1;
+	if (!strcmp(argv[1], "set")) {
+		func = argv[2];
+		state = argv[3];
+		for (i = 0; i < 32; i++) {
+			if (!pwr_mng_bit_func[i])
+				continue;
+			if (!strcmp(func, pwr_mng_bit_func[i]))
+				break;
+		}
+		if (i == 32) {
+			printf("Error: name '%s' not known\n", func);
+			return -1;
+		}
+		val = state[0] != '0';
+		pwr_mng_ctrl_reg |= (val << i);
+		pwr_mng_ctrl_reg &= ~(!val << i);
+		reg_write(POWER_MNG_CTRL_REG, pwr_mng_ctrl_reg);
+	}
+	return 0;
+}
+
+static int do_syno(cmd_tbl_t *cmdtp, int flag,
+                   int argc, char * const argv[])
+{
+	const char *cmd;
+	int ret = 0;
+
+	if (argc < 2)
+		goto usage;
+
+	cmd = argv[1];
+	--argc;
+	++argv;
+
+	if (!strcmp(cmd, "populate_env"))
+		ret = do_syno_populate(argc, argv);
+	else if (!strcmp(cmd, "clk_gate"))
+		ret = do_syno_clk_gate(argc, argv);
+
+	if (ret != -1)
+		return ret;
+usage:
+	return CMD_RET_USAGE;
+}
+
+U_BOOT_CMD(
+	syno, 5, 1, do_syno,
+	"Synology specific commands",
+	"populate_env                 - Read vendor data from SPI flash into environment\n"
+	"clk_gate (get|set name 1|0)  - Manage clock gating\n"
+);
diff --git a/board/Synology/ds414/Makefile b/board/Synology/ds414/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..0f4c32d57ca31b82ce025ebb9bba160be651c0c5
--- /dev/null
+++ b/board/Synology/ds414/Makefile
@@ -0,0 +1,7 @@
+#
+# Copyright (C) 2015 Phil Sutter <phil@nwl.cc>
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y :=	ds414.o
diff --git a/board/Synology/ds414/ds414.c b/board/Synology/ds414/ds414.c
new file mode 100644
index 0000000000000000000000000000000000000000..d563e896f31fef7e0903e2ff05e4f449c1600b49
--- /dev/null
+++ b/board/Synology/ds414/ds414.c
@@ -0,0 +1,185 @@
+/*
+ *
+ * Copyright (C) 2015 Phil Sutter <phil@nwl.cc>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <miiphy.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+#include <linux/mbus.h>
+
+#include "../drivers/ddr/marvell/axp/ddr3_hw_training.h"
+#include "../arch/arm/mach-mvebu/serdes/axp/high_speed_env_spec.h"
+#include "../arch/arm/mach-mvebu/serdes/axp/board_env_spec.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* GPP and MPP settings as found in mvBoardEnvSpec.c of Synology's U-Boot */
+
+#define DS414_GPP_OUT_VAL_LOW		(BIT(25) | BIT(30))
+#define DS414_GPP_OUT_VAL_MID		(BIT(10) | BIT(15))
+#define DS414_GPP_OUT_VAL_HIGH		(0)
+
+#define DS414_GPP_OUT_POL_LOW		(0)
+#define DS414_GPP_OUT_POL_MID		(0)
+#define DS414_GPP_OUT_POL_HIGH		(0)
+
+#define DS414_GPP_OUT_ENA_LOW		(~(BIT(25) | BIT(30)))
+#define DS414_GPP_OUT_ENA_MID		(~(BIT(10) | BIT(12) | \
+					   BIT(13) | BIT(14) | BIT(15)))
+#define DS414_GPP_OUT_ENA_HIGH		(~0)
+
+static const u32 ds414_mpp_control[] = {
+	0x11111111,
+	0x22221111,
+	0x22222222,
+	0x00000000,
+	0x11110000,
+	0x00004000,
+	0x00000000,
+	0x00000000,
+	0x00000000
+};
+
+/* DDR3 static MC configuration */
+
+/* 1G_v1 (4x2Gbits) adapted by DS414 */
+MV_DRAM_MC_INIT syno_ddr3_b0_667_1g_v1[MV_MAX_DDR3_STATIC_SIZE] = {
+	{0x00001400, 0x73014A28},	/*DDR SDRAM Configuration Register */
+	{0x00001404, 0x30000800},	/*Dunit Control Low Register */
+	{0x00001408, 0x44148887},	/*DDR SDRAM Timing (Low) Register */
+	{0x0000140C, 0x3AD83FEA},	/*DDR SDRAM Timing (High) Register */
+
+	{0x00001410, 0x14000000},	/*DDR SDRAM Address Control Register */
+
+	{0x00001414, 0x00000000},	/*DDR SDRAM Open Pages Control Register */
+	{0x00001418, 0x00000e00},	/*DDR SDRAM Operation Register */
+	{0x00001420, 0x00000004},	/*DDR SDRAM Extended Mode Register */
+	{0x00001424, 0x0000F3FF},	/*Dunit Control High Register */
+	{0x00001428, 0x000F8830},	/*Dunit Control High Register */
+	{0x0000142C, 0x054C36F4},	/*Dunit Control High Register */
+	{0x0000147C, 0x0000C671},
+
+	{0x000014a0, 0x00000001},
+	{0x000014a8, 0x00000100},	/*2:1 */
+	{0x00020220, 0x00000006},
+
+	{0x00001494, 0x00010000},	/*DDR SDRAM ODT Control (Low) Register */
+	{0x00001498, 0x00000000},	/*DDR SDRAM ODT Control (High) Register */
+	{0x0000149C, 0x00000001},	/*DDR Dunit ODT Control Register */
+
+	{0x000014C0, 0x192424C9},	/* DRAM address and Control Driving Strenght  */
+	{0x000014C4, 0x0AAA24C9},	/* DRAM Data and DQS Driving Strenght  */
+
+	{0x000200e8, 0x3FFF0E01},	/* DO NOT Modify - Open Mbus Window - 2G - Mbus is required for the training sequence*/
+	{0x00020184, 0x3FFFFFE0},	/* DO NOT Modify - Close fast path Window to - 2G */
+
+	{0x0001504, 0x3FFFFFE1},	/* CS0 Size */
+	{0x000150C, 0x00000000},	/* CS1 Size */
+	{0x0001514, 0x00000000},	/* CS2 Size */
+	{0x000151C, 0x00000000},	/* CS3 Size */
+
+	{0x00001538, 0x00000009},	/*Read Data Sample Delays Register */
+	{0x0000153C, 0x00000009},	/*Read Data Ready Delay Register */
+
+	{0x000015D0, 0x00000650},	/*MR0 */
+	{0x000015D4, 0x00000044},	/*MR1 */
+	{0x000015D8, 0x00000010},	/*MR2 */
+	{0x000015DC, 0x00000000},	/*MR3 */
+
+	{0x000015E4, 0x00203c18},	/*ZQC Configuration Register */
+	{0x000015EC, 0xF800A225},	/*DDR PHY */
+
+	{0x0, 0x0}
+};
+
+MV_DRAM_MODES ds414_ddr_modes[MV_DDR3_MODES_NUMBER] = {
+	{"ds414_1333-667",   0x3, 0x5, 0x0, A0, syno_ddr3_b0_667_1g_v1,  NULL},
+};
+
+extern MV_SERDES_CHANGE_M_PHY serdes_change_m_phy[];
+
+MV_BIN_SERDES_CFG ds414_serdes_cfg[] = {
+	{ MV_PEX_ROOT_COMPLEX, 0x02011111, 0x00000000,
+	  { PEX_BUS_MODE_X4, PEX_BUS_MODE_X1, PEX_BUS_DISABLED,
+	    PEX_BUS_DISABLED },
+	  0x0040, serdes_change_m_phy
+	}
+};
+
+MV_DRAM_MODES *ddr3_get_static_ddr_mode(void)
+{
+	return &ds414_ddr_modes[0];
+}
+
+MV_BIN_SERDES_CFG *board_serdes_cfg_get(u8 pex_mode)
+{
+	return &ds414_serdes_cfg[0];
+}
+
+u8 board_sat_r_get(u8 dev_num, u8 reg)
+{
+	return (0x1 << 1 | 1);
+}
+
+int board_early_init_f(void)
+{
+	int i;
+
+	/* Set GPP Out value */
+	reg_write(GPP_DATA_OUT_REG(0), DS414_GPP_OUT_VAL_LOW);
+	reg_write(GPP_DATA_OUT_REG(1), DS414_GPP_OUT_VAL_MID);
+	reg_write(GPP_DATA_OUT_REG(2), DS414_GPP_OUT_VAL_HIGH);
+
+	/* set GPP polarity */
+	reg_write(GPP_DATA_IN_POL_REG(0), DS414_GPP_OUT_POL_LOW);
+	reg_write(GPP_DATA_IN_POL_REG(1), DS414_GPP_OUT_POL_MID);
+	reg_write(GPP_DATA_IN_POL_REG(2), DS414_GPP_OUT_POL_HIGH);
+
+	/* Set GPP Out Enable */
+	reg_write(GPP_DATA_OUT_EN_REG(0), DS414_GPP_OUT_ENA_LOW);
+	reg_write(GPP_DATA_OUT_EN_REG(1), DS414_GPP_OUT_ENA_MID);
+	reg_write(GPP_DATA_OUT_EN_REG(2), DS414_GPP_OUT_ENA_HIGH);
+
+	for (i = 0; i < ARRAY_SIZE(ds414_mpp_control); i++)
+		reg_write(MPP_CONTROL_REG(i), ds414_mpp_control[i]);
+
+	return 0;
+}
+
+int board_init(void)
+{
+	u32 pwr_mng_ctrl_reg;
+
+	/* Adress of boot parameters */
+	gd->bd->bi_boot_params = mvebu_sdram_bar(0) + 0x100;
+
+	/* Gate unused clocks
+	 *
+	 * Note: Disabling unused PCIe lanes will hang PCI bus scan.
+	 *       Once this is resolved, bits 10-12, 26 and 27 can be
+	 *       unset here as well.
+	 */
+	pwr_mng_ctrl_reg = reg_read(POWER_MNG_CTRL_REG);
+	pwr_mng_ctrl_reg &= ~(BIT(0));				/* Audio */
+	pwr_mng_ctrl_reg &= ~(BIT(1) | BIT(2));			/* GE3, GE2 */
+	pwr_mng_ctrl_reg &= ~(BIT(14) | BIT(15));		/* SATA0 link and core */
+	pwr_mng_ctrl_reg &= ~(BIT(16));				/* LCD */
+	pwr_mng_ctrl_reg &= ~(BIT(17));				/* SDIO */
+	pwr_mng_ctrl_reg &= ~(BIT(19) | BIT(20));		/* USB1 and USB2 */
+	pwr_mng_ctrl_reg &= ~(BIT(29) | BIT(30));		/* SATA1 link and core */
+	reg_write(POWER_MNG_CTRL_REG, pwr_mng_ctrl_reg);
+
+	return 0;
+}
+
+int checkboard(void)
+{
+	puts("Board: DS414\n");
+
+	return 0;
+}
diff --git a/board/Synology/ds414/kwbimage.cfg b/board/Synology/ds414/kwbimage.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..1f748db37c1e5b5b3d160a2f8fa8e7aed200a163
--- /dev/null
+++ b/board/Synology/ds414/kwbimage.cfg
@@ -0,0 +1,12 @@
+#
+# Copyright (C) 2014 Stefan Roese <sr@denx.de>
+#
+
+# Armada XP uses version 1 image format
+VERSION		1
+
+# Boot Media configurations
+BOOT_FROM	spi
+
+# Binary Header (bin_hdr) with DDR3 training code
+BINARY spl/u-boot-spl-dtb.bin 0000005b 00000068
diff --git a/board/maxbcm/Kconfig b/board/maxbcm/Kconfig
deleted file mode 100644
index 2edccfea535d6b13c039580f8fd31424055d1099..0000000000000000000000000000000000000000
--- a/board/maxbcm/Kconfig
+++ /dev/null
@@ -1,9 +0,0 @@
-if TARGET_MAXBCM
-
-config SYS_BOARD
-	default "maxbcm"
-
-config SYS_CONFIG_NAME
-	default "maxbcm"
-
-endif
diff --git a/board/maxbcm/kwbimage.cfg b/board/maxbcm/kwbimage.cfg
index cc057925566c584d66b0dc73207f5a62523ad2f6..1f748db37c1e5b5b3d160a2f8fa8e7aed200a163 100644
--- a/board/maxbcm/kwbimage.cfg
+++ b/board/maxbcm/kwbimage.cfg
@@ -9,4 +9,4 @@ VERSION		1
 BOOT_FROM	spi
 
 # Binary Header (bin_hdr) with DDR3 training code
-BINARY spl/u-boot-spl.bin 0000005b 00000068
+BINARY spl/u-boot-spl-dtb.bin 0000005b 00000068
diff --git a/board/maxbcm/maxbcm.c b/board/maxbcm/maxbcm.c
index 119ba4c6c8f670f84d8afb21aeeeed2eebbafbf6..db6ad99efea10da9a5f07dd33034dc498aad7d6d 100644
--- a/board/maxbcm/maxbcm.c
+++ b/board/maxbcm/maxbcm.c
@@ -138,17 +138,15 @@ int checkboard(void)
 	return 0;
 }
 
-#ifdef CONFIG_RESET_PHY_R
 /* Configure and enable MV88E6185 switch */
-void reset_phy(void)
+int board_phy_config(struct phy_device *phydev)
 {
-	char *name = "neta0";
-
-	if (miiphy_set_current_dev(name))
-		return;
-
-	/* todo: fill this with the real setup / config code */
-
-	printf("88E6185 Initialized on %s\n", name);
+	/*
+	 * todo:
+	 * Fill this with the real setup / config code.
+	 * Please see board/Marvell/db-mv784mp-gp/db-mv784mp-gp.c
+	 * for details.
+	 */
+	printf("88E6185 Initialized\n");
+	return 0;
 }
-#endif /* CONFIG_RESET_PHY_R */
diff --git a/board/solidrun/clearfog/MAINTAINERS b/board/solidrun/clearfog/MAINTAINERS
new file mode 100644
index 0000000000000000000000000000000000000000..298e5011c79615ec8c7ea5c36193540a2fff4b23
--- /dev/null
+++ b/board/solidrun/clearfog/MAINTAINERS
@@ -0,0 +1,6 @@
+CLEARFOG BOARD
+M:	Stefan Roese <sr@denx.de>
+S:	Maintained
+F:	board/soldrun/clearfog/
+F:	include/configs/clearfog.h
+F:	configs/clearfog_defconfig
diff --git a/board/solidrun/clearfog/Makefile b/board/solidrun/clearfog/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..1920d6bf6d932877575c79c9897231348220878e
--- /dev/null
+++ b/board/solidrun/clearfog/Makefile
@@ -0,0 +1,7 @@
+#
+# Copyright (C) 2015 Stefan Roese <sr@denx.de>
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y	:= clearfog.o
diff --git a/board/solidrun/clearfog/README b/board/solidrun/clearfog/README
new file mode 100644
index 0000000000000000000000000000000000000000..2cfa5bfc8637334869339a1bb0ad8135674e7441
--- /dev/null
+++ b/board/solidrun/clearfog/README
@@ -0,0 +1,18 @@
+Update from original Marvell U-Boot to mainline U-Boot:
+-------------------------------------------------------
+
+Generate the U-Boot image with these commands:
+
+$ make clearfog_defconfig
+$ make
+
+The resulting image including the SPL binary with the
+full DDR setup is "u-boot-spl.kwb".
+
+Now all you need to do is copy this image on a SD card.
+For example with this command:
+
+$ sudo dd if=u-boot-spl.kwb of=/dev/sdX bs=512 seek=1
+
+Please use the correct device node for your setup instead
+of "/dev/sdX" here!
diff --git a/board/solidrun/clearfog/clearfog.c b/board/solidrun/clearfog/clearfog.c
new file mode 100644
index 0000000000000000000000000000000000000000..2773f5957e6e101321aa4d7990624c60555db5c1
--- /dev/null
+++ b/board/solidrun/clearfog/clearfog.c
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2015 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <miiphy.h>
+#include <netdev.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+
+#include "../drivers/ddr/marvell/a38x/ddr3_a38x_topology.h"
+#include <../serdes/a38x/high_speed_env_spec.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define ETH_PHY_CTRL_REG		0
+#define ETH_PHY_CTRL_POWER_DOWN_BIT	11
+#define ETH_PHY_CTRL_POWER_DOWN_MASK	(1 << ETH_PHY_CTRL_POWER_DOWN_BIT)
+
+/*
+ * Those values and defines are taken from the Marvell U-Boot version
+ * "u-boot-2013.01-15t1-clearfog"
+ */
+#define BOARD_GPP_OUT_ENA_LOW	0xffffffff
+#define BOARD_GPP_OUT_ENA_MID	0xffffffff
+
+#define BOARD_GPP_OUT_VAL_LOW	0x0
+#define BOARD_GPP_OUT_VAL_MID	0x0
+#define BOARD_GPP_POL_LOW	0x0
+#define BOARD_GPP_POL_MID	0x0
+
+/* IO expander on Marvell GP board includes e.g. fan enabling */
+struct marvell_io_exp {
+	u8 chip;
+	u8 addr;
+	u8 val;
+};
+
+static struct marvell_io_exp io_exp[] = {
+	{ 0x20, 2, 0x40 },	/* Deassert both mini pcie reset signals */
+	{ 0x20, 6, 0xf9 },
+	{ 0x20, 2, 0x46 },	/* rst signals and ena USB3 current limiter */
+	{ 0x20, 6, 0xb9 },
+	{ 0x20, 3, 0x00 },	/* Set SFP_TX_DIS to zero */
+	{ 0x20, 7, 0xbf },	/* Drive SFP_TX_DIS to zero */
+};
+
+static struct serdes_map board_serdes_map[] = {
+	{SATA0, SERDES_SPEED_3_GBPS, SERDES_DEFAULT_MODE, 0, 0},
+	{SGMII1, SERDES_SPEED_1_25_GBPS, SERDES_DEFAULT_MODE, 0, 0},
+	{PEX1, SERDES_SPEED_5_GBPS, PEX_ROOT_COMPLEX_X1, 0, 0},
+	{USB3_HOST1, SERDES_SPEED_5_GBPS, SERDES_DEFAULT_MODE, 0, 0},
+	{PEX2, SERDES_SPEED_5_GBPS, PEX_ROOT_COMPLEX_X1, 0, 0},
+	{SGMII2, SERDES_SPEED_1_25_GBPS, SERDES_DEFAULT_MODE, 0, 0},
+};
+
+int hws_board_topology_load(struct serdes_map **serdes_map_array, u8 *count)
+{
+	*serdes_map_array = board_serdes_map;
+	*count = ARRAY_SIZE(board_serdes_map);
+	return 0;
+}
+
+/*
+ * Define the DDR layout / topology here in the board file. This will
+ * be used by the DDR3 init code in the SPL U-Boot version to configure
+ * the DDR3 controller.
+ */
+static struct hws_topology_map board_topology_map = {
+	0x1, /* active interfaces */
+	/* cs_mask, mirror, dqs_swap, ck_swap X PUPs */
+	{ { { {0x1, 0, 0, 0},
+	      {0x1, 0, 0, 0},
+	      {0x1, 0, 0, 0},
+	      {0x1, 0, 0, 0},
+	      {0x1, 0, 0, 0} },
+	    SPEED_BIN_DDR_1600K,	/* speed_bin */
+	    BUS_WIDTH_16,		/* memory_width */
+	    MEM_4G,			/* mem_size */
+	    DDR_FREQ_800,		/* frequency */
+	    0, 0,			/* cas_l cas_wl */
+	    HWS_TEMP_LOW} },		/* temperature */
+	5,				/* Num Of Bus Per Interface*/
+	BUS_MASK_32BIT			/* Busses mask */
+};
+
+struct hws_topology_map *ddr3_get_topology_map(void)
+{
+	/* Return the board topology as defined in the board code */
+	return &board_topology_map;
+}
+
+int board_early_init_f(void)
+{
+	/* Configure MPP */
+	writel(0x11111111, MVEBU_MPP_BASE + 0x00);
+	writel(0x11111111, MVEBU_MPP_BASE + 0x04);
+	writel(0x10400011, MVEBU_MPP_BASE + 0x08);
+	writel(0x22043333, MVEBU_MPP_BASE + 0x0c);
+	writel(0x44400002, MVEBU_MPP_BASE + 0x10);
+	writel(0x41144004, MVEBU_MPP_BASE + 0x14);
+	writel(0x40333333, MVEBU_MPP_BASE + 0x18);
+	writel(0x00004444, MVEBU_MPP_BASE + 0x1c);
+
+	/* Set GPP Out value */
+	writel(BOARD_GPP_OUT_VAL_LOW, MVEBU_GPIO0_BASE + 0x00);
+	writel(BOARD_GPP_OUT_VAL_MID, MVEBU_GPIO1_BASE + 0x00);
+
+	/* Set GPP Polarity */
+	writel(BOARD_GPP_POL_LOW, MVEBU_GPIO0_BASE + 0x0c);
+	writel(BOARD_GPP_POL_MID, MVEBU_GPIO1_BASE + 0x0c);
+
+	/* Set GPP Out Enable */
+	writel(BOARD_GPP_OUT_ENA_LOW, MVEBU_GPIO0_BASE + 0x04);
+	writel(BOARD_GPP_OUT_ENA_MID, MVEBU_GPIO1_BASE + 0x04);
+
+	return 0;
+}
+
+int board_init(void)
+{
+	int i;
+
+	/* Address of boot parameters */
+	gd->bd->bi_boot_params = mvebu_sdram_bar(0) + 0x100;
+
+	/* Toggle GPIO41 to reset onboard switch and phy */
+	clrbits_le32(MVEBU_GPIO1_BASE + 0x0, BIT(9));
+	clrbits_le32(MVEBU_GPIO1_BASE + 0x4, BIT(9));
+	mdelay(1);
+	setbits_le32(MVEBU_GPIO1_BASE + 0x0, BIT(9));
+	mdelay(10);
+
+	/* Init I2C IO expanders */
+	for (i = 0; i < ARRAY_SIZE(io_exp); i++)
+		i2c_write(io_exp[i].chip, io_exp[i].addr, 1, &io_exp[i].val, 1);
+
+	return 0;
+}
+
+int checkboard(void)
+{
+	puts("Board: SolidRun ClearFog\n");
+
+	return 0;
+}
+
+int board_eth_init(bd_t *bis)
+{
+	cpu_eth_init(bis); /* Built in controller(s) come first */
+	return pci_eth_init(bis);
+}
diff --git a/board/solidrun/clearfog/kwbimage.cfg b/board/solidrun/clearfog/kwbimage.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..c650c2c65eb5949cda3abda497e9882b5711ef5b
--- /dev/null
+++ b/board/solidrun/clearfog/kwbimage.cfg
@@ -0,0 +1,12 @@
+#
+# Copyright (C) 2015 Stefan Roese <sr@denx.de>
+#
+
+# Armada XP uses version 1 image format
+VERSION		1
+
+# Boot Media configurations
+BOOT_FROM	sdio
+
+# Binary Header (bin_hdr) with DDR3 training code
+BINARY spl/u-boot-spl-dtb.bin 0000005b 00000068
diff --git a/configs/clearfog_defconfig b/configs/clearfog_defconfig
new file mode 100644
index 0000000000000000000000000000000000000000..57d6a64b436c8e83af9f462414badc481bb2a919
--- /dev/null
+++ b/configs/clearfog_defconfig
@@ -0,0 +1,21 @@
+CONFIG_ARM=y
+CONFIG_ARCH_MVEBU=y
+CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_TARGET_CLEARFOG=y
+CONFIG_DEFAULT_DEVICE_TREE="armada-388-clearfog"
+CONFIG_SPL=y
+# CONFIG_CMD_IMLS is not set
+# CONFIG_CMD_FLASH is not set
+CONFIG_CMD_USB=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_SPL_OF_TRANSLATE=y
+CONFIG_SPI_FLASH=y
+CONFIG_DEBUG_UART=y
+CONFIG_DEBUG_UART_BASE=0xd0012000
+CONFIG_DEBUG_UART_CLOCK=250000000
+CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_SYS_NS16550=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_STORAGE=y
diff --git a/configs/db-88f6820-gp_defconfig b/configs/db-88f6820-gp_defconfig
index cdcd34cb478e49e19ca0b553c27632d9f5fb0062..111f3a14216fcb516d8f4881ec494d494a3355a8 100644
--- a/configs/db-88f6820-gp_defconfig
+++ b/configs/db-88f6820-gp_defconfig
@@ -1,5 +1,6 @@
 CONFIG_ARM=y
 CONFIG_ARCH_MVEBU=y
+CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_TARGET_DB_88F6820_GP=y
 CONFIG_DEFAULT_DEVICE_TREE="armada-388-gp"
 CONFIG_SPL=y
@@ -7,9 +8,14 @@ CONFIG_SPL=y
 # CONFIG_CMD_FLASH is not set
 CONFIG_CMD_USB=y
 # CONFIG_CMD_SETEXPR is not set
+CONFIG_SPL_OF_TRANSLATE=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_MACRONIX=y
 CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_DEBUG_UART=y
+CONFIG_DEBUG_UART_BASE=0xd0012000
+CONFIG_DEBUG_UART_CLOCK=250000000
+CONFIG_DEBUG_UART_SHIFT=2
 CONFIG_SYS_NS16550=y
 CONFIG_USB=y
 CONFIG_DM_USB=y
diff --git a/configs/db-mv784mp-gp_defconfig b/configs/db-mv784mp-gp_defconfig
index 4c4329dc783ca87212eed2f83a493024c85633fb..6dda2ae32b7b88f09c1dca377db827eec018a608 100644
--- a/configs/db-mv784mp-gp_defconfig
+++ b/configs/db-mv784mp-gp_defconfig
@@ -1,16 +1,23 @@
 CONFIG_ARM=y
 CONFIG_ARCH_MVEBU=y
+CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_TARGET_DB_MV784MP_GP=y
 CONFIG_DEFAULT_DEVICE_TREE="armada-xp-gp"
+# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 CONFIG_SPL=y
 # CONFIG_CMD_IMLS is not set
 # CONFIG_CMD_FLASH is not set
 CONFIG_CMD_USB=y
 # CONFIG_CMD_SETEXPR is not set
+CONFIG_SPL_OF_TRANSLATE=y
 CONFIG_NAND_PXA3XX=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_MACRONIX=y
 CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_DEBUG_UART=y
+CONFIG_DEBUG_UART_BASE=0xd0012000
+CONFIG_DEBUG_UART_CLOCK=250000000
+CONFIG_DEBUG_UART_SHIFT=2
 CONFIG_SYS_NS16550=y
 CONFIG_USB=y
 CONFIG_DM_USB=y
diff --git a/configs/ds414_defconfig b/configs/ds414_defconfig
new file mode 100644
index 0000000000000000000000000000000000000000..4c3c1df63da20e83a2b04b7647e8e78939a1df11
--- /dev/null
+++ b/configs/ds414_defconfig
@@ -0,0 +1,18 @@
+CONFIG_ARM=y
+CONFIG_ARCH_MVEBU=y
+CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_TARGET_DS414=y
+CONFIG_DEFAULT_DEVICE_TREE="armada-xp-synology-ds414"
+CONFIG_SPL=y
+# CONFIG_CMD_IMLS is not set
+# CONFIG_CMD_FLASH is not set
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_SPL_OF_TRANSLATE=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_BAR=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_DEBUG_UART=y
+CONFIG_DEBUG_UART_BASE=0xd0012000
+CONFIG_DEBUG_UART_CLOCK=250000000
+CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_SYS_NS16550=y
diff --git a/configs/maxbcm_defconfig b/configs/maxbcm_defconfig
index 921c6c43670fd85826022edae8563f66acf63768..200c7a04261a37ba197b1966c13f660da03eb69c 100644
--- a/configs/maxbcm_defconfig
+++ b/configs/maxbcm_defconfig
@@ -1,14 +1,20 @@
 CONFIG_ARM=y
 CONFIG_ARCH_MVEBU=y
+CONFIG_SYS_MALLOC_F_LEN=0x2000
 CONFIG_TARGET_MAXBCM=y
-CONFIG_DEFAULT_DEVICE_TREE="armada-xp-gp"
+CONFIG_DEFAULT_DEVICE_TREE="armada-xp-maxbcm"
 CONFIG_SPL=y
 # CONFIG_CMD_IMLS is not set
 # CONFIG_CMD_FLASH is not set
 # CONFIG_CMD_SETEXPR is not set
+CONFIG_SPL_OF_TRANSLATE=y
 CONFIG_SPI_FLASH=y
 CONFIG_SPI_FLASH_BAR=y
 CONFIG_SPI_FLASH_MACRONIX=y
 CONFIG_SPI_FLASH_SPANSION=y
 CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_DEBUG_UART=y
+CONFIG_DEBUG_UART_BASE=0xd0012000
+CONFIG_DEBUG_UART_CLOCK=250000000
+CONFIG_DEBUG_UART_SHIFT=2
 CONFIG_SYS_NS16550=y
diff --git a/drivers/Makefile b/drivers/Makefile
index c9031f2ce877842fd02d3446d9b1fe159ba0a2e1..00da40b704a705c2ac4645b68b61b294f7dcddc8 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -14,8 +14,8 @@ obj-$(CONFIG_SPL_I2C_SUPPORT) += i2c/
 obj-$(CONFIG_SPL_GPIO_SUPPORT) += gpio/
 obj-$(CONFIG_SPL_MMC_SUPPORT) += mmc/
 obj-$(CONFIG_SPL_MPC8XXX_INIT_DDR_SUPPORT) += ddr/fsl/
-obj-$(CONFIG_SYS_MVEBU_DDR_A38X) += ddr/marvell/a38x/
-obj-$(CONFIG_SYS_MVEBU_DDR_AXP) += ddr/marvell/axp/
+obj-$(CONFIG_ARMADA_38X) += ddr/marvell/a38x/
+obj-$(CONFIG_ARMADA_XP) += ddr/marvell/axp/
 obj-$(CONFIG_ALTERA_SDRAM) += ddr/altera/
 obj-$(CONFIG_SPL_SERIAL_SUPPORT) += serial/
 obj-$(CONFIG_SPL_SPI_FLASH_SUPPORT) += mtd/spi/
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index f161c01c67dc72d1a2964e3ba0c0c7c5e07fda1a..eb8bda9ab2c61cf4d48a8702b747b569fa50fa94 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_MVSATA_IDE) += mvsata_ide.o
 obj-$(CONFIG_MX51_PATA) += mxc_ata.o
 obj-$(CONFIG_PATA_BFIN) += pata_bfin.o
 obj-$(CONFIG_SATA_DWC) += sata_dwc.o
+obj-$(CONFIG_SATA_MV) += sata_mv.o
 obj-$(CONFIG_SATA_SIL3114) += sata_sil3114.o
 obj-$(CONFIG_SATA_SIL) += sata_sil.o
 obj-$(CONFIG_IDE_SIL680) += sil680.o
diff --git a/drivers/block/mvsata_ide.c b/drivers/block/mvsata_ide.c
index 52c16025f8987e352f259befae07a8fb2b5d65ae..2c6d42410cb2dbf2ed28898b05457baced780ef2 100644
--- a/drivers/block/mvsata_ide.c
+++ b/drivers/block/mvsata_ide.c
@@ -13,7 +13,7 @@
 #include <asm/arch/orion5x.h>
 #elif defined(CONFIG_KIRKWOOD)
 #include <asm/arch/soc.h>
-#elif defined(CONFIG_ARMADA_XP)
+#elif defined(CONFIG_ARCH_MVEBU)
 #include <linux/mbus.h>
 #endif
 
@@ -102,7 +102,7 @@ struct mvsata_port_registers {
  * Initialize SATA memory windows for Armada XP
  */
 
-#ifdef CONFIG_ARMADA_XP
+#ifdef CONFIG_ARCH_MVEBU
 static void mvsata_ide_conf_mbus_windows(void)
 {
 	const struct mbus_dram_target_info *dram;
@@ -174,7 +174,7 @@ int ide_preinit(void)
 	int ret = MVSATA_STATUS_TIMEOUT;
 	int status;
 
-#ifdef CONFIG_ARMADA_XP
+#ifdef CONFIG_ARCH_MVEBU
 	mvsata_ide_conf_mbus_windows();
 #endif
 
diff --git a/drivers/block/sata_mv.c b/drivers/block/sata_mv.c
new file mode 100644
index 0000000000000000000000000000000000000000..88249341d647db690ffa05fa41e04451da0e5844
--- /dev/null
+++ b/drivers/block/sata_mv.c
@@ -0,0 +1,1045 @@
+/*
+ * Copyright (C) Excito Elektronik i Skåne AB, 2010.
+ * Author: Tor Krill <tor@excito.com>
+ *
+ * Copyright (C) 2015 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/*
+ * This driver supports the SATA controller of some Mavell SoC's.
+ * Here a (most likely incomplete) list of the supported SoC's:
+ * - Kirkwood
+ * - Armada 370
+ * - Armada XP
+ *
+ * This driver implementation is an alternative to the already available
+ * driver via the "ide" commands interface (drivers/block/mvsata_ide.c).
+ * But this driver only supports PIO mode and as this new driver also
+ * supports transfer via DMA, its much faster.
+ *
+ * Please note, that the newer SoC's (e.g. Armada 38x) are not supported
+ * by this driver. As they have an AHCI compatible SATA controller
+ * integrated.
+ */
+
+/*
+ * TODO:
+ * Better error recovery
+ * No support for using PRDs (Thus max 64KB transfers)
+ * No NCQ support
+ * No port multiplier support
+ */
+
+#include <common.h>
+#include <fis.h>
+#include <libata.h>
+#include <malloc.h>
+#include <sata.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <linux/mbus.h>
+
+#if defined(CONFIG_KIRKWOOD)
+#include <asm/arch/kirkwood.h>
+#define SATAHC_BASE		KW_SATA_BASE
+#else
+#include <asm/arch/soc.h>
+#define SATAHC_BASE		MVEBU_AXP_SATA_BASE
+#endif
+
+#define SATA0_BASE		(SATAHC_BASE + 0x2000)
+#define SATA1_BASE		(SATAHC_BASE + 0x4000)
+
+/* EDMA registers */
+#define EDMA_CFG		0x000
+#define EDMA_CFG_NCQ		(1 << 5)
+#define EDMA_CFG_EQUE		(1 << 9)
+#define EDMA_TIMER		0x004
+#define EDMA_IECR		0x008
+#define EDMA_IEMR		0x00c
+#define EDMA_RQBA_HI		0x010
+#define EDMA_RQIPR		0x014
+#define EDMA_RQIPR_IPMASK	(0x1f << 5)
+#define EDMA_RQIPR_IPSHIFT	5
+#define EDMA_RQOPR		0x018
+#define EDMA_RQOPR_OPMASK	(0x1f << 5)
+#define EDMA_RQOPR_OPSHIFT	5
+#define EDMA_RSBA_HI		0x01c
+#define EDMA_RSIPR		0x020
+#define EDMA_RSIPR_IPMASK	(0x1f << 3)
+#define EDMA_RSIPR_IPSHIFT	3
+#define	EDMA_RSOPR		0x024
+#define EDMA_RSOPR_OPMASK	(0x1f << 3)
+#define EDMA_RSOPR_OPSHIFT	3
+#define EDMA_CMD		0x028
+#define EDMA_CMD_ENEDMA		(0x01 << 0)
+#define EDMA_CMD_DISEDMA	(0x01 << 1)
+#define EDMA_CMD_ATARST		(0x01 << 2)
+#define EDMA_CMD_FREEZE		(0x01 << 4)
+#define EDMA_TEST_CTL		0x02c
+#define EDMA_STATUS		0x030
+#define EDMA_IORTO		0x034
+#define EDMA_CDTR		0x040
+#define EDMA_HLTCND		0x060
+#define EDMA_NTSR		0x094
+
+/* Basic DMA registers */
+#define BDMA_CMD		0x224
+#define BDMA_STATUS		0x228
+#define BDMA_DTLB		0x22c
+#define BDMA_DTHB		0x230
+#define BDMA_DRL		0x234
+#define BDMA_DRH		0x238
+
+/* SATA Interface registers */
+#define SIR_ICFG		0x050
+#define SIR_CFG_GEN2EN		(0x1 << 7)
+#define SIR_PLL_CFG		0x054
+#define SIR_SSTATUS		0x300
+#define SSTATUS_DET_MASK	(0x0f << 0)
+#define SIR_SERROR		0x304
+#define SIR_SCONTROL		0x308
+#define SIR_SCONTROL_DETEN	(0x01 << 0)
+#define SIR_LTMODE		0x30c
+#define SIR_LTMODE_NELBE	(0x01 << 7)
+#define SIR_PHYMODE3		0x310
+#define SIR_PHYMODE4		0x314
+#define SIR_PHYMODE1		0x32c
+#define SIR_PHYMODE2		0x330
+#define SIR_BIST_CTRL		0x334
+#define SIR_BIST_DW1		0x338
+#define SIR_BIST_DW2		0x33c
+#define SIR_SERR_IRQ_MASK	0x340
+#define SIR_SATA_IFCTRL		0x344
+#define SIR_SATA_TESTCTRL	0x348
+#define SIR_SATA_IFSTATUS	0x34c
+#define SIR_VEND_UNIQ		0x35c
+#define SIR_FIS_CFG		0x360
+#define SIR_FIS_IRQ_CAUSE	0x364
+#define SIR_FIS_IRQ_MASK	0x368
+#define SIR_FIS_DWORD0		0x370
+#define SIR_FIS_DWORD1		0x374
+#define SIR_FIS_DWORD2		0x378
+#define SIR_FIS_DWORD3		0x37c
+#define SIR_FIS_DWORD4		0x380
+#define SIR_FIS_DWORD5		0x384
+#define SIR_FIS_DWORD6		0x388
+#define SIR_PHYM9_GEN2		0x398
+#define SIR_PHYM9_GEN1		0x39c
+#define SIR_PHY_CFG		0x3a0
+#define SIR_PHYCTL		0x3a4
+#define SIR_PHYM10		0x3a8
+#define SIR_PHYM12		0x3b0
+
+/* Shadow registers */
+#define	PIO_DATA		0x100
+#define PIO_ERR_FEATURES	0x104
+#define PIO_SECTOR_COUNT	0x108
+#define PIO_LBA_LOW		0x10c
+#define PIO_LBA_MID		0x110
+#define PIO_LBA_HI		0x114
+#define PIO_DEVICE		0x118
+#define PIO_CMD_STATUS		0x11c
+#define PIO_STATUS_ERR		(0x01 << 0)
+#define PIO_STATUS_DRQ		(0x01 << 3)
+#define PIO_STATUS_DF		(0x01 << 5)
+#define PIO_STATUS_DRDY		(0x01 << 6)
+#define PIO_STATUS_BSY		(0x01 << 7)
+#define PIO_CTRL_ALTSTAT	0x120
+
+/* SATAHC arbiter registers */
+#define SATAHC_CFG		0x000
+#define SATAHC_RQOP		0x004
+#define SATAHC_RQIP		0x008
+#define SATAHC_ICT		0x00c
+#define SATAHC_ITT		0x010
+#define SATAHC_ICR		0x014
+#define SATAHC_ICR_PORT0	(0x01 << 0)
+#define SATAHC_ICR_PORT1	(0x01 << 1)
+#define SATAHC_MIC		0x020
+#define SATAHC_MIM		0x024
+#define SATAHC_LED_CFG		0x02c
+
+#define REQUEST_QUEUE_SIZE	32
+#define RESPONSE_QUEUE_SIZE	REQUEST_QUEUE_SIZE
+
+struct crqb {
+	u32 dtb_low;		/* DW0 */
+	u32 dtb_high;		/* DW1 */
+	u32 control_flags;	/* DW2 */
+	u32 drb_count;		/* DW3 */
+	u32 ata_cmd_feat;	/* DW4 */
+	u32 ata_addr;		/* DW5 */
+	u32 ata_addr_exp;	/* DW6 */
+	u32 ata_sect_count;	/* DW7 */
+};
+
+#define CRQB_ALIGN			0x400
+
+#define CRQB_CNTRLFLAGS_DIR		(0x01 << 0)
+#define CRQB_CNTRLFLAGS_DQTAGMASK	(0x1f << 1)
+#define CRQB_CNTRLFLAGS_DQTAGSHIFT	1
+#define CRQB_CNTRLFLAGS_PMPORTMASK	(0x0f << 12)
+#define CRQB_CNTRLFLAGS_PMPORTSHIFT	12
+#define CRQB_CNTRLFLAGS_PRDMODE		(0x01 << 16)
+#define CRQB_CNTRLFLAGS_HQTAGMASK	(0x1f << 17)
+#define CRQB_CNTRLFLAGS_HQTAGSHIFT	17
+
+#define CRQB_CMDFEAT_CMDMASK		(0xff << 16)
+#define CRQB_CMDFEAT_CMDSHIFT		16
+#define CRQB_CMDFEAT_FEATMASK		(0xff << 16)
+#define CRQB_CMDFEAT_FEATSHIFT		24
+
+#define CRQB_ADDR_LBA_LOWMASK		(0xff << 0)
+#define CRQB_ADDR_LBA_LOWSHIFT		0
+#define CRQB_ADDR_LBA_MIDMASK		(0xff << 8)
+#define CRQB_ADDR_LBA_MIDSHIFT		8
+#define CRQB_ADDR_LBA_HIGHMASK		(0xff << 16)
+#define CRQB_ADDR_LBA_HIGHSHIFT		16
+#define CRQB_ADDR_DEVICE_MASK		(0xff << 24)
+#define CRQB_ADDR_DEVICE_SHIFT		24
+
+#define CRQB_ADDR_LBA_LOW_EXP_MASK	(0xff << 0)
+#define CRQB_ADDR_LBA_LOW_EXP_SHIFT	0
+#define CRQB_ADDR_LBA_MID_EXP_MASK	(0xff << 8)
+#define CRQB_ADDR_LBA_MID_EXP_SHIFT	8
+#define CRQB_ADDR_LBA_HIGH_EXP_MASK	(0xff << 16)
+#define CRQB_ADDR_LBA_HIGH_EXP_SHIFT	16
+#define CRQB_ADDR_FEATURE_EXP_MASK	(0xff << 24)
+#define CRQB_ADDR_FEATURE_EXP_SHIFT	24
+
+#define CRQB_SECTCOUNT_COUNT_MASK	(0xff << 0)
+#define CRQB_SECTCOUNT_COUNT_SHIFT	0
+#define CRQB_SECTCOUNT_COUNT_EXP_MASK	(0xff << 8)
+#define CRQB_SECTCOUNT_COUNT_EXP_SHIFT	8
+
+#define MVSATA_WIN_CONTROL(w)	(MVEBU_AXP_SATA_BASE + 0x30 + ((w) << 4))
+#define MVSATA_WIN_BASE(w)	(MVEBU_AXP_SATA_BASE + 0x34 + ((w) << 4))
+
+struct eprd {
+	u32 phyaddr_low;
+	u32 bytecount_eot;
+	u32 phyaddr_hi;
+	u32 reserved;
+};
+
+#define EPRD_PHYADDR_MASK	0xfffffffe
+#define EPRD_BYTECOUNT_MASK	0x0000ffff
+#define EPRD_EOT		(0x01 << 31)
+
+struct crpb {
+	u32 id;
+	u32 flags;
+	u32 timestamp;
+};
+
+#define CRPB_ALIGN		0x100
+
+#define READ_CMD		0
+#define WRITE_CMD		1
+
+/*
+ * Since we don't use PRDs yet max transfer size
+ * is 64KB
+ */
+#define MV_ATA_MAX_SECTORS	(65535 / ATA_SECT_SIZE)
+
+/* Keep track if hw is initialized or not */
+static u32 hw_init;
+
+struct mv_priv {
+	char name[12];
+	u32 link;
+	u32 regbase;
+	u32 queue_depth;
+	u16 pio;
+	u16 mwdma;
+	u16 udma;
+
+	void *crqb_alloc;
+	struct crqb *request;
+
+	void *crpb_alloc;
+	struct crpb *response;
+};
+
+static int ata_wait_register(u32 *addr, u32 mask, u32 val, u32 timeout_msec)
+{
+	ulong start;
+
+	start = get_timer(0);
+	do {
+		if ((in_le32(addr) & mask) == val)
+			return 0;
+	} while (get_timer(start) < timeout_msec);
+
+	return -ETIMEDOUT;
+}
+
+/* Cut from sata_mv in linux kernel */
+static int mv_stop_edma_engine(int port)
+{
+	struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
+	int i;
+
+	/* Disable eDMA. The disable bit auto clears. */
+	out_le32(priv->regbase + EDMA_CMD, EDMA_CMD_DISEDMA);
+
+	/* Wait for the chip to confirm eDMA is off. */
+	for (i = 10000; i > 0; i--) {
+		u32 reg = in_le32(priv->regbase + EDMA_CMD);
+		if (!(reg & EDMA_CMD_ENEDMA)) {
+			debug("EDMA stop on port %d succesful\n", port);
+			return 0;
+		}
+		udelay(10);
+	}
+	debug("EDMA stop on port %d failed\n", port);
+	return -1;
+}
+
+static int mv_start_edma_engine(int port)
+{
+	struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
+	u32 tmp;
+
+	/* Check preconditions */
+	tmp = in_le32(priv->regbase + SIR_SSTATUS);
+	if ((tmp & SSTATUS_DET_MASK) != 0x03) {
+		printf("Device error on port: %d\n", port);
+		return -1;
+	}
+
+	tmp = in_le32(priv->regbase + PIO_CMD_STATUS);
+	if (tmp & (ATA_BUSY | ATA_DRQ)) {
+		printf("Device not ready on port: %d\n", port);
+		return -1;
+	}
+
+	/* Clear interrupt cause */
+	out_le32(priv->regbase + EDMA_IECR, 0x0);
+
+	tmp = in_le32(SATAHC_BASE + SATAHC_ICR);
+	tmp &= ~(port == 0 ? SATAHC_ICR_PORT0 : SATAHC_ICR_PORT1);
+	out_le32(SATAHC_BASE + SATAHC_ICR, tmp);
+
+	/* Configure edma operation */
+	tmp = in_le32(priv->regbase + EDMA_CFG);
+	tmp &= ~EDMA_CFG_NCQ;	/* No NCQ */
+	tmp &= ~EDMA_CFG_EQUE;	/* Dont queue operations */
+	out_le32(priv->regbase + EDMA_CFG, tmp);
+
+	out_le32(priv->regbase + SIR_FIS_IRQ_CAUSE, 0x0);
+
+	/* Configure fis, set all to no-wait for now */
+	out_le32(priv->regbase + SIR_FIS_CFG, 0x0);
+
+	/* Setup request queue */
+	out_le32(priv->regbase + EDMA_RQBA_HI, 0x0);
+	out_le32(priv->regbase + EDMA_RQIPR, priv->request);
+	out_le32(priv->regbase + EDMA_RQOPR, 0x0);
+
+	/* Setup response queue */
+	out_le32(priv->regbase + EDMA_RSBA_HI, 0x0);
+	out_le32(priv->regbase + EDMA_RSOPR, priv->response);
+	out_le32(priv->regbase + EDMA_RSIPR, 0x0);
+
+	/* Start edma */
+	out_le32(priv->regbase + EDMA_CMD, EDMA_CMD_ENEDMA);
+
+	return 0;
+}
+
+static int mv_reset_channel(int port)
+{
+	struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
+
+	/* Make sure edma is stopped  */
+	mv_stop_edma_engine(port);
+
+	out_le32(priv->regbase + EDMA_CMD, EDMA_CMD_ATARST);
+	udelay(25);		/* allow reset propagation */
+	out_le32(priv->regbase + EDMA_CMD, 0);
+	mdelay(10);
+
+	return 0;
+}
+
+static void mv_reset_port(int port)
+{
+	struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
+
+	mv_reset_channel(port);
+
+	out_le32(priv->regbase + EDMA_CMD, 0x0);
+	out_le32(priv->regbase + EDMA_CFG, 0x101f);
+	out_le32(priv->regbase + EDMA_IECR, 0x0);
+	out_le32(priv->regbase + EDMA_IEMR, 0x0);
+	out_le32(priv->regbase + EDMA_RQBA_HI, 0x0);
+	out_le32(priv->regbase + EDMA_RQIPR, 0x0);
+	out_le32(priv->regbase + EDMA_RQOPR, 0x0);
+	out_le32(priv->regbase + EDMA_RSBA_HI, 0x0);
+	out_le32(priv->regbase + EDMA_RSIPR, 0x0);
+	out_le32(priv->regbase + EDMA_RSOPR, 0x0);
+	out_le32(priv->regbase + EDMA_IORTO, 0xfa);
+}
+
+static void mv_reset_one_hc(void)
+{
+	out_le32(SATAHC_BASE + SATAHC_ICT, 0x00);
+	out_le32(SATAHC_BASE + SATAHC_ITT, 0x00);
+	out_le32(SATAHC_BASE + SATAHC_ICR, 0x00);
+}
+
+static int probe_port(int port)
+{
+	struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
+	int tries, tries2, set15 = 0;
+	u32 tmp;
+
+	debug("Probe port: %d\n", port);
+
+	for (tries = 0; tries < 2; tries++) {
+		/* Clear SError */
+		out_le32(priv->regbase + SIR_SERROR, 0x0);
+
+		/* trigger com-init */
+		tmp = in_le32(priv->regbase + SIR_SCONTROL);
+		tmp = (tmp & 0x0f0) | 0x300 | SIR_SCONTROL_DETEN;
+		out_le32(priv->regbase + SIR_SCONTROL, tmp);
+
+		mdelay(1);
+
+		tmp = in_le32(priv->regbase + SIR_SCONTROL);
+		tries2 = 5;
+		do {
+			tmp = (tmp & 0x0f0) | 0x300;
+			out_le32(priv->regbase + SIR_SCONTROL, tmp);
+			mdelay(10);
+			tmp = in_le32(priv->regbase + SIR_SCONTROL);
+		} while ((tmp & 0xf0f) != 0x300 && tries2--);
+
+		mdelay(10);
+
+		for (tries2 = 0; tries2 < 200; tries2++) {
+			tmp = in_le32(priv->regbase + SIR_SSTATUS);
+			if ((tmp & SSTATUS_DET_MASK) == 0x03) {
+				debug("Found device on port\n");
+				return 0;
+			}
+			mdelay(1);
+		}
+
+		if ((tmp & SSTATUS_DET_MASK) == 0) {
+			debug("No device attached on port %d\n", port);
+			return -ENODEV;
+		}
+
+		if (!set15) {
+			/* Try on 1.5Gb/S */
+			debug("Try 1.5Gb link\n");
+			set15 = 1;
+			out_le32(priv->regbase + SIR_SCONTROL, 0x304);
+
+			tmp = in_le32(priv->regbase + SIR_ICFG);
+			tmp &= ~SIR_CFG_GEN2EN;
+			out_le32(priv->regbase + SIR_ICFG, tmp);
+
+			mv_reset_channel(port);
+		}
+	}
+
+	debug("Failed to probe port\n");
+	return -1;
+}
+
+/* Get request queue in pointer */
+static int get_reqip(int port)
+{
+	struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
+	u32 tmp;
+
+	tmp = in_le32(priv->regbase + EDMA_RQIPR) & EDMA_RQIPR_IPMASK;
+	tmp = tmp >> EDMA_RQIPR_IPSHIFT;
+
+	return tmp;
+}
+
+static void set_reqip(int port, int reqin)
+{
+	struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
+	u32 tmp;
+
+	tmp = in_le32(priv->regbase + EDMA_RQIPR) & ~EDMA_RQIPR_IPMASK;
+	tmp |= ((reqin << EDMA_RQIPR_IPSHIFT) & EDMA_RQIPR_IPMASK);
+	out_le32(priv->regbase + EDMA_RQIPR, tmp);
+}
+
+/* Get next available slot, ignoring possible overwrite */
+static int get_next_reqip(int port)
+{
+	int slot = get_reqip(port);
+	slot = (slot + 1) % REQUEST_QUEUE_SIZE;
+	return slot;
+}
+
+/* Get response queue in pointer */
+static int get_rspip(int port)
+{
+	struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
+	u32 tmp;
+
+	tmp = in_le32(priv->regbase + EDMA_RSIPR) & EDMA_RSIPR_IPMASK;
+	tmp = tmp >> EDMA_RSIPR_IPSHIFT;
+
+	return tmp;
+}
+
+/* Get response queue out pointer */
+static int get_rspop(int port)
+{
+	struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
+	u32 tmp;
+
+	tmp = in_le32(priv->regbase + EDMA_RSOPR) & EDMA_RSOPR_OPMASK;
+	tmp = tmp >> EDMA_RSOPR_OPSHIFT;
+	return tmp;
+}
+
+/* Get next response queue pointer  */
+static int get_next_rspop(int port)
+{
+	return (get_rspop(port) + 1) % RESPONSE_QUEUE_SIZE;
+}
+
+/* Set response queue pointer */
+static void set_rspop(int port, int reqin)
+{
+	struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
+	u32 tmp;
+
+	tmp = in_le32(priv->regbase + EDMA_RSOPR) & ~EDMA_RSOPR_OPMASK;
+	tmp |= ((reqin << EDMA_RSOPR_OPSHIFT) & EDMA_RSOPR_OPMASK);
+
+	out_le32(priv->regbase + EDMA_RSOPR, tmp);
+}
+
+static int wait_dma_completion(int port, int index, u32 timeout_msec)
+{
+	u32 tmp, res;
+
+	tmp = port == 0 ? SATAHC_ICR_PORT0 : SATAHC_ICR_PORT1;
+	res = ata_wait_register((u32 *)(SATAHC_BASE + SATAHC_ICR), tmp,
+				tmp, timeout_msec);
+	if (res)
+		printf("Failed to wait for completion on port %d\n", port);
+
+	return res;
+}
+
+static void process_responses(int port)
+{
+#ifdef DEBUG
+	struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
+#endif
+	u32 tmp;
+	u32 outind = get_rspop(port);
+
+	/* Ack interrupts */
+	tmp = in_le32(SATAHC_BASE + SATAHC_ICR);
+	if (port == 0)
+		tmp &= ~(BIT(0) | BIT(8));
+	else
+		tmp &= ~(BIT(1) | BIT(9));
+	tmp &= ~(BIT(4));
+	out_le32(SATAHC_BASE + SATAHC_ICR, tmp);
+
+	while (get_rspip(port) != outind) {
+#ifdef DEBUG
+		debug("Response index %d flags %08x on port %d\n", outind,
+		      priv->response[outind].flags, port);
+#endif
+		outind = get_next_rspop(port);
+		set_rspop(port, outind);
+	}
+}
+
+static int mv_ata_exec_ata_cmd(int port, struct sata_fis_h2d *cfis,
+			       u8 *buffer, u32 len, u32 iswrite)
+{
+	struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
+	struct crqb *req;
+	int slot;
+
+	if (len >= 64 * 1024) {
+		printf("We only support <64K transfers for now\n");
+		return -1;
+	}
+
+	/* Initialize request */
+	slot = get_reqip(port);
+	memset(&priv->request[slot], 0, sizeof(struct crqb));
+	req = &priv->request[slot];
+
+	req->dtb_low = (u32)buffer;
+
+	/* Dont use PRDs */
+	req->control_flags = CRQB_CNTRLFLAGS_PRDMODE;
+	req->control_flags |= iswrite ? 0 : CRQB_CNTRLFLAGS_DIR;
+	req->control_flags |=
+	    ((cfis->pm_port_c << CRQB_CNTRLFLAGS_PMPORTSHIFT)
+	     & CRQB_CNTRLFLAGS_PMPORTMASK);
+
+	req->drb_count = len;
+
+	req->ata_cmd_feat = (cfis->command << CRQB_CMDFEAT_CMDSHIFT) &
+		CRQB_CMDFEAT_CMDMASK;
+	req->ata_cmd_feat |= (cfis->features << CRQB_CMDFEAT_FEATSHIFT) &
+		CRQB_CMDFEAT_FEATMASK;
+
+	req->ata_addr = (cfis->lba_low << CRQB_ADDR_LBA_LOWSHIFT) &
+		CRQB_ADDR_LBA_LOWMASK;
+	req->ata_addr |= (cfis->lba_mid << CRQB_ADDR_LBA_MIDSHIFT) &
+		CRQB_ADDR_LBA_MIDMASK;
+	req->ata_addr |= (cfis->lba_high << CRQB_ADDR_LBA_HIGHSHIFT) &
+		CRQB_ADDR_LBA_HIGHMASK;
+	req->ata_addr |= (cfis->device << CRQB_ADDR_DEVICE_SHIFT) &
+		CRQB_ADDR_DEVICE_MASK;
+
+	req->ata_addr_exp = (cfis->lba_low_exp << CRQB_ADDR_LBA_LOW_EXP_SHIFT) &
+		CRQB_ADDR_LBA_LOW_EXP_MASK;
+	req->ata_addr_exp |=
+		(cfis->lba_mid_exp << CRQB_ADDR_LBA_MID_EXP_SHIFT) &
+		CRQB_ADDR_LBA_MID_EXP_MASK;
+	req->ata_addr_exp |=
+		(cfis->lba_high_exp << CRQB_ADDR_LBA_HIGH_EXP_SHIFT) &
+		CRQB_ADDR_LBA_HIGH_EXP_MASK;
+	req->ata_addr_exp |=
+		(cfis->features_exp << CRQB_ADDR_FEATURE_EXP_SHIFT) &
+		CRQB_ADDR_FEATURE_EXP_MASK;
+
+	req->ata_sect_count =
+		(cfis->sector_count << CRQB_SECTCOUNT_COUNT_SHIFT) &
+		CRQB_SECTCOUNT_COUNT_MASK;
+	req->ata_sect_count |=
+		(cfis->sector_count_exp << CRQB_SECTCOUNT_COUNT_EXP_SHIFT) &
+		CRQB_SECTCOUNT_COUNT_EXP_MASK;
+
+	/* Flush data */
+	flush_dcache_range((u32)req, (u32)req + sizeof(*req));
+
+	/* Trigger operation */
+	slot = get_next_reqip(port);
+	set_reqip(port, slot);
+
+	/* Wait for completion */
+	if (wait_dma_completion(port, slot, 10000)) {
+		printf("ATA operation timed out\n");
+		return -1;
+	}
+
+	process_responses(port);
+
+	/* Invalidate data on read */
+	if (buffer && len)
+		invalidate_dcache_range((u32)buffer, (u32)buffer + len);
+
+	return len;
+}
+
+static u32 mv_sata_rw_cmd_ext(int port, lbaint_t start, u32 blkcnt,
+			      u8 *buffer, int is_write)
+{
+	struct sata_fis_h2d cfis;
+	u32 res;
+	u64 block;
+
+	block = (u64)start;
+
+	memset(&cfis, 0, sizeof(struct sata_fis_h2d));
+
+	cfis.fis_type = SATA_FIS_TYPE_REGISTER_H2D;
+	cfis.command = (is_write) ? ATA_CMD_WRITE_EXT : ATA_CMD_READ_EXT;
+
+	cfis.lba_high_exp = (block >> 40) & 0xff;
+	cfis.lba_mid_exp = (block >> 32) & 0xff;
+	cfis.lba_low_exp = (block >> 24) & 0xff;
+	cfis.lba_high = (block >> 16) & 0xff;
+	cfis.lba_mid = (block >> 8) & 0xff;
+	cfis.lba_low = block & 0xff;
+	cfis.device = ATA_LBA;
+	cfis.sector_count_exp = (blkcnt >> 8) & 0xff;
+	cfis.sector_count = blkcnt & 0xff;
+
+	res = mv_ata_exec_ata_cmd(port, &cfis, buffer, ATA_SECT_SIZE * blkcnt,
+				  is_write);
+
+	return res >= 0 ? blkcnt : res;
+}
+
+static u32 mv_sata_rw_cmd(int port, lbaint_t start, u32 blkcnt, u8 *buffer,
+			  int is_write)
+{
+	struct sata_fis_h2d cfis;
+	lbaint_t block;
+	u32 res;
+
+	block = start;
+
+	memset(&cfis, 0, sizeof(struct sata_fis_h2d));
+
+	cfis.fis_type = SATA_FIS_TYPE_REGISTER_H2D;
+	cfis.command = (is_write) ? ATA_CMD_WRITE : ATA_CMD_READ;
+	cfis.device = ATA_LBA;
+
+	cfis.device |= (block >> 24) & 0xf;
+	cfis.lba_high = (block >> 16) & 0xff;
+	cfis.lba_mid = (block >> 8) & 0xff;
+	cfis.lba_low = block & 0xff;
+	cfis.sector_count = (u8)(blkcnt & 0xff);
+
+	res = mv_ata_exec_ata_cmd(port, &cfis, buffer, ATA_SECT_SIZE * blkcnt,
+				  is_write);
+
+	return res >= 0 ? blkcnt : res;
+}
+
+static u32 ata_low_level_rw(int dev, lbaint_t blknr, lbaint_t blkcnt,
+			    void *buffer, int is_write)
+{
+	lbaint_t start, blks;
+	u8 *addr;
+	int max_blks;
+
+	debug("%s: %ld %ld\n", __func__, blknr, blkcnt);
+
+	start = blknr;
+	blks = blkcnt;
+	addr = (u8 *)buffer;
+
+	max_blks = MV_ATA_MAX_SECTORS;
+	do {
+		if (blks > max_blks) {
+			if (sata_dev_desc[dev].lba48) {
+				mv_sata_rw_cmd_ext(dev, start, max_blks, addr,
+						   is_write);
+			} else {
+				mv_sata_rw_cmd(dev, start, max_blks, addr,
+					       is_write);
+			}
+			start += max_blks;
+			blks -= max_blks;
+			addr += ATA_SECT_SIZE * max_blks;
+		} else {
+			if (sata_dev_desc[dev].lba48) {
+				mv_sata_rw_cmd_ext(dev, start, blks, addr,
+						   is_write);
+			} else {
+				mv_sata_rw_cmd(dev, start, blks, addr,
+					       is_write);
+			}
+			start += blks;
+			blks = 0;
+			addr += ATA_SECT_SIZE * blks;
+		}
+	} while (blks != 0);
+
+	return blkcnt;
+}
+
+static int mv_ata_exec_ata_cmd_nondma(int port,
+				      struct sata_fis_h2d *cfis, u8 *buffer,
+				      u32 len, u32 iswrite)
+{
+	struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
+	int i;
+	u16 *tp;
+
+	debug("%s\n", __func__);
+
+	out_le32(priv->regbase + PIO_SECTOR_COUNT, cfis->sector_count);
+	out_le32(priv->regbase + PIO_LBA_HI, cfis->lba_high);
+	out_le32(priv->regbase + PIO_LBA_MID, cfis->lba_mid);
+	out_le32(priv->regbase + PIO_LBA_LOW, cfis->lba_low);
+	out_le32(priv->regbase + PIO_ERR_FEATURES, cfis->features);
+	out_le32(priv->regbase + PIO_DEVICE, cfis->device);
+	out_le32(priv->regbase + PIO_CMD_STATUS, cfis->command);
+
+	if (ata_wait_register((u32 *)(priv->regbase + PIO_CMD_STATUS),
+			      ATA_BUSY, 0x0, 10000)) {
+		debug("Failed to wait for completion\n");
+		return -1;
+	}
+
+	if (len > 0) {
+		tp = (u16 *)buffer;
+		for (i = 0; i < len / 2; i++) {
+			if (iswrite)
+				out_le16(priv->regbase + PIO_DATA, *tp++);
+			else
+				*tp++ = in_le16(priv->regbase + PIO_DATA);
+		}
+	}
+
+	return len;
+}
+
+static int mv_sata_identify(int port, u16 *id)
+{
+	struct sata_fis_h2d h2d;
+
+	memset(&h2d, 0, sizeof(struct sata_fis_h2d));
+
+	h2d.fis_type = SATA_FIS_TYPE_REGISTER_H2D;
+	h2d.command = ATA_CMD_ID_ATA;
+
+	/* Give device time to get operational */
+	mdelay(10);
+
+	return mv_ata_exec_ata_cmd_nondma(port, &h2d, (u8 *)id,
+					  ATA_ID_WORDS * 2, READ_CMD);
+}
+
+static void mv_sata_xfer_mode(int port, u16 *id)
+{
+	struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
+
+	priv->pio = id[ATA_ID_PIO_MODES];
+	priv->mwdma = id[ATA_ID_MWDMA_MODES];
+	priv->udma = id[ATA_ID_UDMA_MODES];
+	debug("pio %04x, mwdma %04x, udma %04x\n", priv->pio, priv->mwdma,
+	      priv->udma);
+}
+
+static void mv_sata_set_features(int port)
+{
+	struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
+	struct sata_fis_h2d cfis;
+	u8 udma_cap;
+
+	memset(&cfis, 0, sizeof(struct sata_fis_h2d));
+
+	cfis.fis_type = SATA_FIS_TYPE_REGISTER_H2D;
+	cfis.command = ATA_CMD_SET_FEATURES;
+	cfis.features = SETFEATURES_XFER;
+
+	/* First check the device capablity */
+	udma_cap = (u8) (priv->udma & 0xff);
+
+	if (udma_cap == ATA_UDMA6)
+		cfis.sector_count = XFER_UDMA_6;
+	if (udma_cap == ATA_UDMA5)
+		cfis.sector_count = XFER_UDMA_5;
+	if (udma_cap == ATA_UDMA4)
+		cfis.sector_count = XFER_UDMA_4;
+	if (udma_cap == ATA_UDMA3)
+		cfis.sector_count = XFER_UDMA_3;
+
+	mv_ata_exec_ata_cmd_nondma(port, &cfis, NULL, 0, READ_CMD);
+}
+
+int mv_sata_spin_down(int dev)
+{
+	struct sata_fis_h2d cfis;
+	struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[dev].priv;
+
+	if (priv->link == 0) {
+		debug("No device on port: %d\n", dev);
+		return 1;
+	}
+
+	memset(&cfis, 0, sizeof(struct sata_fis_h2d));
+
+	cfis.fis_type = SATA_FIS_TYPE_REGISTER_H2D;
+	cfis.command = ATA_CMD_STANDBY;
+
+	return mv_ata_exec_ata_cmd_nondma(dev, &cfis, NULL, 0, READ_CMD);
+}
+
+int mv_sata_spin_up(int dev)
+{
+	struct sata_fis_h2d cfis;
+	struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[dev].priv;
+
+	if (priv->link == 0) {
+		debug("No device on port: %d\n", dev);
+		return 1;
+	}
+
+	memset(&cfis, 0, sizeof(struct sata_fis_h2d));
+
+	cfis.fis_type = SATA_FIS_TYPE_REGISTER_H2D;
+	cfis.command = ATA_CMD_IDLE;
+
+	return mv_ata_exec_ata_cmd_nondma(dev, &cfis, NULL, 0, READ_CMD);
+}
+
+ulong sata_read(int dev, ulong blknr, lbaint_t blkcnt, void *buffer)
+{
+	return ata_low_level_rw(dev, blknr, blkcnt, buffer, READ_CMD);
+}
+
+ulong sata_write(int dev, ulong blknr, lbaint_t blkcnt, const void *buffer)
+{
+	return ata_low_level_rw(dev, blknr, blkcnt, (void *)buffer, WRITE_CMD);
+}
+
+/*
+ * Initialize SATA memory windows
+ */
+static void mvsata_ide_conf_mbus_windows(void)
+{
+	const struct mbus_dram_target_info *dram;
+	int i;
+
+	dram = mvebu_mbus_dram_info();
+
+	/* Disable windows, Set Size/Base to 0  */
+	for (i = 0; i < 4; i++) {
+		writel(0, MVSATA_WIN_CONTROL(i));
+		writel(0, MVSATA_WIN_BASE(i));
+	}
+
+	for (i = 0; i < dram->num_cs; i++) {
+		const struct mbus_dram_window *cs = dram->cs + i;
+		writel(((cs->size - 1) & 0xffff0000) | (cs->mbus_attr << 8) |
+		       (dram->mbus_dram_target_id << 4) | 1,
+		       MVSATA_WIN_CONTROL(i));
+		writel(cs->base & 0xffff0000, MVSATA_WIN_BASE(i));
+	}
+}
+
+int init_sata(int dev)
+{
+	struct mv_priv *priv;
+
+	debug("Initialize sata dev: %d\n", dev);
+
+	if (dev < 0 || dev >= CONFIG_SYS_SATA_MAX_DEVICE) {
+		printf("Invalid sata device %d\n", dev);
+		return -1;
+	}
+
+	priv = (struct mv_priv *)malloc(sizeof(struct mv_priv));
+	if (!priv) {
+		printf("Failed to allocate memory for private sata data\n");
+		return -ENOMEM;
+	}
+
+	memset((void *)priv, 0, sizeof(struct mv_priv));
+
+	/* Allocate and align request buffer */
+	priv->crqb_alloc = malloc(sizeof(struct crqb) * REQUEST_QUEUE_SIZE +
+				  CRQB_ALIGN);
+	if (!priv->crqb_alloc) {
+		printf("Unable to allocate memory for request queue\n");
+		return -ENOMEM;
+	}
+	memset(priv->crqb_alloc, 0,
+	       sizeof(struct crqb) * REQUEST_QUEUE_SIZE + CRQB_ALIGN);
+	priv->request = (struct crqb *)(((u32) priv->crqb_alloc + CRQB_ALIGN) &
+					~(CRQB_ALIGN - 1));
+
+	/* Allocate and align response buffer */
+	priv->crpb_alloc = malloc(sizeof(struct crpb) * REQUEST_QUEUE_SIZE +
+				  CRPB_ALIGN);
+	if (!priv->crpb_alloc) {
+		printf("Unable to allocate memory for response queue\n");
+		return -ENOMEM;
+	}
+	memset(priv->crpb_alloc, 0,
+	       sizeof(struct crpb) * REQUEST_QUEUE_SIZE + CRPB_ALIGN);
+	priv->response = (struct crpb *)(((u32) priv->crpb_alloc + CRPB_ALIGN) &
+					 ~(CRPB_ALIGN - 1));
+
+	sata_dev_desc[dev].priv = (void *)priv;
+
+	sprintf(priv->name, "SATA%d", dev);
+
+	priv->regbase = dev == 0 ? SATA0_BASE : SATA1_BASE;
+
+	if (!hw_init) {
+		debug("Initialize sata hw\n");
+		hw_init = 1;
+		mv_reset_one_hc();
+		mvsata_ide_conf_mbus_windows();
+	}
+
+	mv_reset_port(dev);
+
+	if (probe_port(dev)) {
+		priv->link = 0;
+		return -ENODEV;
+	}
+	priv->link = 1;
+
+	return 0;
+}
+
+int reset_sata(int dev)
+{
+	return 0;
+}
+
+int scan_sata(int port)
+{
+	unsigned char serial[ATA_ID_SERNO_LEN + 1];
+	unsigned char firmware[ATA_ID_FW_REV_LEN + 1];
+	unsigned char product[ATA_ID_PROD_LEN + 1];
+	u64 n_sectors;
+	u16 *id;
+	struct mv_priv *priv = (struct mv_priv *)sata_dev_desc[port].priv;
+
+	if (!priv->link)
+		return -ENODEV;
+
+	id = (u16 *)malloc(ATA_ID_WORDS * 2);
+	if (!id) {
+		printf("Failed to malloc id data\n");
+		return -ENOMEM;
+	}
+
+	mv_sata_identify(port, id);
+	ata_swap_buf_le16(id, ATA_ID_WORDS);
+#ifdef DEBUG
+	ata_dump_id(id);
+#endif
+
+	/* Serial number */
+	ata_id_c_string(id, serial, ATA_ID_SERNO, sizeof(serial));
+	memcpy(sata_dev_desc[port].product, serial, sizeof(serial));
+
+	/* Firmware version */
+	ata_id_c_string(id, firmware, ATA_ID_FW_REV, sizeof(firmware));
+	memcpy(sata_dev_desc[port].revision, firmware, sizeof(firmware));
+
+	/* Product model */
+	ata_id_c_string(id, product, ATA_ID_PROD, sizeof(product));
+	memcpy(sata_dev_desc[port].vendor, product, sizeof(product));
+
+	/* Total sectors */
+	n_sectors = ata_id_n_sectors(id);
+	sata_dev_desc[port].lba = n_sectors;
+
+	/* Check if support LBA48 */
+	if (ata_id_has_lba48(id)) {
+		sata_dev_desc[port].lba48 = 1;
+		debug("Device support LBA48\n");
+	}
+
+	/* Get the NCQ queue depth from device */
+	priv->queue_depth = ata_id_queue_depth(id);
+
+	/* Get the xfer mode from device */
+	mv_sata_xfer_mode(port, id);
+
+	/* Set the xfer mode to highest speed */
+	mv_sata_set_features(port);
+
+	/* Start up */
+	mv_start_edma_engine(port);
+
+	return 0;
+}
diff --git a/drivers/ddr/marvell/a38x/ddr3_debug.c b/drivers/ddr/marvell/a38x/ddr3_debug.c
index 1d72bc569e4bbf2579d6f1eb9008f2e1a471e1ca..12b5b04109d3e5090121ada7b075a907a6b4e057 100644
--- a/drivers/ddr/marvell/a38x/ddr3_debug.c
+++ b/drivers/ddr/marvell/a38x/ddr3_debug.c
@@ -164,21 +164,6 @@ int ddr3_tip_init_config_func(u32 dev_num,
 	return MV_OK;
 }
 
-/*
- * Read training result table
- */
-int hws_ddr3_tip_read_training_result(
-	u32 dev_num, enum hws_result result[MAX_STAGE_LIMIT][MAX_INTERFACE_NUM])
-{
-	dev_num = dev_num;
-
-	if (result == NULL)
-		return MV_BAD_PARAM;
-	memcpy(result, training_result, sizeof(result));
-
-	return MV_OK;
-}
-
 /*
  * Get training result info pointer
  */
diff --git a/drivers/ddr/marvell/a38x/ddr3_training_ip.h b/drivers/ddr/marvell/a38x/ddr3_training_ip.h
index 76a1b6a06d49bc65332c03a44cd93a3b6bba2722..ed92873697e3978fcedbed27fbd4743d62f4d29a 100644
--- a/drivers/ddr/marvell/a38x/ddr3_training_ip.h
+++ b/drivers/ddr/marvell/a38x/ddr3_training_ip.h
@@ -171,8 +171,6 @@ int hws_ddr3_tip_load_topology_map(u32 dev_num,
 				   struct hws_topology_map *topology);
 int hws_ddr3_tip_run_alg(u32 dev_num, enum hws_algo_type algo_type);
 int hws_ddr3_tip_mode_read(u32 dev_num, struct mode_info *mode_info);
-int hws_ddr3_tip_read_training_result(u32 dev_num,
-		enum hws_result result[MAX_STAGE_LIMIT][MAX_INTERFACE_NUM]);
 int ddr3_tip_is_pup_lock(u32 *pup_buf, enum hws_training_result read_mode);
 u8 ddr3_tip_get_buf_min(u8 *buf_ptr);
 u8 ddr3_tip_get_buf_max(u8 *buf_ptr);
diff --git a/drivers/ddr/marvell/axp/ddr3_axp.h b/drivers/ddr/marvell/axp/ddr3_axp.h
index d9e33f7c6e25602726d7c8fa077439037862d511..75d315a35e0c28cf91b84cb0a6641bad1eab5514 100644
--- a/drivers/ddr/marvell/axp/ddr3_axp.h
+++ b/drivers/ddr/marvell/axp/ddr3_axp.h
@@ -33,7 +33,10 @@
 #define SAR1_CPU_CORE_MASK		0x00000018
 #define SAR1_CPU_CORE_OFFSET		3
 
+/* Only enable ECC if the board selects it */
+#ifdef CONFIG_BOARD_ECC_SUPPORT
 #define ECC_SUPPORT
+#endif
 #define NEW_FABRIC_TWSI_ADDR		0x4E
 #ifdef CONFIG_DB_784MP_GP
 #define BUS_WIDTH_ECC_TWSI_ADDR		0x4E
diff --git a/drivers/ddr/marvell/axp/ddr3_axp_config.h b/drivers/ddr/marvell/axp/ddr3_axp_config.h
index a6720442ffae5d06c7f9ddd3d4fa8b4e01b5b010..8549fe8babaa37d62d0e49e90094a903a3e3ee0d 100644
--- a/drivers/ddr/marvell/axp/ddr3_axp_config.h
+++ b/drivers/ddr/marvell/axp/ddr3_axp_config.h
@@ -44,9 +44,14 @@
  * DDR3_TRAINING_DEBUG - Debug prints of internal code
  */
 #define DDR_TARGET_FABRIC			5
+/* Only enable ECC if the board selects it */
+#ifdef CONFIG_BOARD_ECC_SUPPORT
 #define DRAM_ECC				1
+#else
+#define DRAM_ECC				0
+#endif
 
-#ifdef MV_DDR_32BIT
+#ifdef CONFIG_DDR_32BIT
 #define BUS_WIDTH                               32
 #else
 #define BUS_WIDTH				64
diff --git a/drivers/ddr/marvell/axp/ddr3_axp_mc_static.h b/drivers/ddr/marvell/axp/ddr3_axp_mc_static.h
index 2c0e9075e96d2ce20f6884c05f49ca889a8ccb82..71794ad312a1b92e60d5255f804f42ce2e5953f6 100644
--- a/drivers/ddr/marvell/axp/ddr3_axp_mc_static.h
+++ b/drivers/ddr/marvell/axp/ddr3_axp_mc_static.h
@@ -8,9 +8,9 @@
 #define __AXP_MC_STATIC_H
 
 MV_DRAM_MC_INIT ddr3_A0_db_667[MV_MAX_DDR3_STATIC_SIZE] = {
-#ifdef MV_DDR_32BIT
+#ifdef CONFIG_DDR_32BIT
 	{0x00001400, 0x7301c924},	/*DDR SDRAM Configuration Register */
-#else /*MV_DDR_64BIT */
+#else /*CONFIG_DDR_64BIT */
 	{0x00001400, 0x7301CA28},	/*DDR SDRAM Configuration Register */
 #endif
 	{0x00001404, 0x3630b800},	/*Dunit Control Low Register */
@@ -66,9 +66,9 @@ MV_DRAM_MC_INIT ddr3_A0_db_667[MV_MAX_DDR3_STATIC_SIZE] = {
 };
 
 MV_DRAM_MC_INIT ddr3_A0_AMC_667[MV_MAX_DDR3_STATIC_SIZE] = {
-#ifdef MV_DDR_32BIT
+#ifdef CONFIG_DDR_32BIT
 	{0x00001400, 0x7301c924},	/*DDR SDRAM Configuration Register */
-#else /*MV_DDR_64BIT */
+#else /*CONFIG_DDR_64BIT */
 	{0x00001400, 0x7301CA28},	/*DDR SDRAM Configuration Register */
 #endif
 	{0x00001404, 0x3630b800},	/*Dunit Control Low Register */
@@ -124,9 +124,9 @@ MV_DRAM_MC_INIT ddr3_A0_AMC_667[MV_MAX_DDR3_STATIC_SIZE] = {
 };
 
 MV_DRAM_MC_INIT ddr3_A0_db_400[MV_MAX_DDR3_STATIC_SIZE] = {
-#ifdef MV_DDR_32BIT
+#ifdef CONFIG_DDR_32BIT
 	{0x00001400, 0x73004C30},	/*DDR SDRAM Configuration Register */
-#else /* MV_DDR_64BIT */
+#else /* CONFIG_DDR_64BIT */
 	{0x00001400, 0x7300CC30},	/*DDR SDRAM Configuration Register */
 #endif
 	{0x00001404, 0x3630B840},	/*Dunit Control Low Register */
@@ -176,9 +176,9 @@ MV_DRAM_MC_INIT ddr3_A0_db_400[MV_MAX_DDR3_STATIC_SIZE] = {
 };
 
 MV_DRAM_MC_INIT ddr3_Z1_db_600[MV_MAX_DDR3_STATIC_SIZE] = {
-#ifdef MV_DDR_32BIT
+#ifdef CONFIG_DDR_32BIT
 	{0x00001400, 0x73014A28},	/*DDR SDRAM Configuration Register */
-#else /*MV_DDR_64BIT */
+#else /*CONFIG_DDR_64BIT */
 	{0x00001400, 0x7301CA28},	/*DDR SDRAM Configuration Register */
 #endif
 	{0x00001404, 0x3630B040},	/*Dunit Control Low Register */
@@ -233,9 +233,9 @@ MV_DRAM_MC_INIT ddr3_Z1_db_600[MV_MAX_DDR3_STATIC_SIZE] = {
 };
 
 MV_DRAM_MC_INIT ddr3_Z1_db_300[MV_MAX_DDR3_STATIC_SIZE] = {
-#ifdef MV_DDR_32BIT
+#ifdef CONFIG_DDR_32BIT
 	{0x00001400, 0x73004C30},	/*DDR SDRAM Configuration Register */
-#else /*MV_DDR_64BIT */
+#else /*CONFIG_DDR_64BIT */
 	{0x00001400, 0x7300CC30},	/*DDR SDRAM Configuration Register */
 	/*{0x00001400, 0x7304CC30},  *//*DDR SDRAM Configuration Register */
 #endif
diff --git a/drivers/ddr/marvell/axp/ddr3_write_leveling.c b/drivers/ddr/marvell/axp/ddr3_write_leveling.c
index df3a3df4a660852591348988eedae6b5f1d6911d..da384f321ca19aa8da3c1bfb606acad99d8ac9a2 100644
--- a/drivers/ddr/marvell/axp/ddr3_write_leveling.c
+++ b/drivers/ddr/marvell/axp/ddr3_write_leveling.c
@@ -22,6 +22,8 @@
 	DEBUG_WL_FULL_S(s); DEBUG_WL_FULL_D(d, l); DEBUG_WL_FULL_S("\n")
 
 #ifdef MV_DEBUG_WL
+#define DEBUG_WL_S(s)			puts(s)
+#define DEBUG_WL_D(d, l)		printf("%x", d)
 #define DEBUG_RL_S(s) \
 	debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_2, "%s", s)
 #define DEBUG_RL_D(d, l) \
@@ -1229,8 +1231,6 @@ static int ddr3_write_leveling_single_cs(u32 cs, u32 freq, int ratio_2to1,
 			DEBUG_WL_FULL_D((u32) phase, 1);
 			DEBUG_WL_FULL_S(", Delay = ");
 			DEBUG_WL_FULL_D((u32) delay, 1);
-			DEBUG_WL_FULL_S(", Counter = ");
-			DEBUG_WL_FULL_D((u32) i, 1);
 			DEBUG_WL_FULL_S("\n");
 
 			/* Drive DQS high for one cycle - All data PUPs */
diff --git a/drivers/i2c/mvtwsi.c b/drivers/i2c/mvtwsi.c
index f20d1b229154d93b530245f2bf935df0e6f32fae..5dc4fbba1fe8c254b99f6f3bf06ddeda5e74ee60 100644
--- a/drivers/i2c/mvtwsi.c
+++ b/drivers/i2c/mvtwsi.c
@@ -20,7 +20,7 @@
 
 #if defined(CONFIG_ORION5X)
 #include <asm/arch/orion5x.h>
-#elif (defined(CONFIG_KIRKWOOD) || defined(CONFIG_ARMADA_XP))
+#elif (defined(CONFIG_KIRKWOOD) || defined(CONFIG_ARCH_MVEBU))
 #include <asm/arch/soc.h>
 #elif defined(CONFIG_SUNXI)
 #include <asm/arch/i2c.h>
diff --git a/drivers/net/mvneta.c b/drivers/net/mvneta.c
index 38ad14eff96dc8a62dc0bba4af2b5a41d8986583..fa20f548e5202032947dac1c49ec33a9ddf2c64b 100644
--- a/drivers/net/mvneta.c
+++ b/drivers/net/mvneta.c
@@ -2,7 +2,7 @@
  * Driver for Marvell NETA network card for Armada XP and Armada 370 SoCs.
  *
  * U-Boot version:
- * Copyright (C) 2014 Stefan Roese <sr@denx.de>
+ * Copyright (C) 2014-2015 Stefan Roese <sr@denx.de>
  *
  * Based on the Linux version which is:
  * Copyright (C) 2012 Marvell
@@ -14,6 +14,7 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <net.h>
 #include <netdev.h>
 #include <config.h>
@@ -28,6 +29,8 @@
 #include <linux/compat.h>
 #include <linux/mbus.h>
 
+DECLARE_GLOBAL_DATA_PTR;
+
 #if !defined(CONFIG_PHYLIB)
 # error Marvell mvneta requires PHYLIB
 #endif
@@ -1115,9 +1118,9 @@ static void mvneta_start_dev(struct mvneta_port *pp)
 	mvneta_port_enable(pp);
 }
 
-static void mvneta_adjust_link(struct eth_device *dev)
+static void mvneta_adjust_link(struct udevice *dev)
 {
-	struct mvneta_port *pp = dev->priv;
+	struct mvneta_port *pp = dev_get_priv(dev);
 	struct phy_device *phydev = pp->phydev;
 	int status_change = 0;
 
@@ -1171,9 +1174,9 @@ static void mvneta_adjust_link(struct eth_device *dev)
 	}
 }
 
-static int mvneta_open(struct eth_device *dev)
+static int mvneta_open(struct udevice *dev)
 {
-	struct mvneta_port *pp = dev->priv;
+	struct mvneta_port *pp = dev_get_priv(dev);
 	int ret;
 
 	ret = mvneta_setup_rxqs(pp);
@@ -1192,7 +1195,7 @@ static int mvneta_open(struct eth_device *dev)
 }
 
 /* Initialize hw */
-static int mvneta_init(struct mvneta_port *pp)
+static int mvneta_init2(struct mvneta_port *pp)
 {
 	int queue;
 
@@ -1314,23 +1317,22 @@ static int mvneta_port_power_up(struct mvneta_port *pp, int phy_mode)
 }
 
 /* Device initialization routine */
-static int mvneta_probe(struct eth_device *dev)
+static int mvneta_init(struct udevice *dev)
 {
-	struct mvneta_port *pp = dev->priv;
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	struct mvneta_port *pp = dev_get_priv(dev);
 	int err;
 
 	pp->tx_ring_size = MVNETA_MAX_TXD;
 	pp->rx_ring_size = MVNETA_MAX_RXD;
 
-	err = mvneta_init(pp);
+	err = mvneta_init2(pp);
 	if (err < 0) {
 		dev_err(&pdev->dev, "can't init eth hal\n");
 		return err;
 	}
 
-	mvneta_conf_mbus_windows(pp);
-
-	mvneta_mac_addr_set(pp, dev->enetaddr, rxq_def);
+	mvneta_mac_addr_set(pp, pdata->enetaddr, rxq_def);
 
 	err = mvneta_port_power_up(pp, pp->phy_interface);
 	if (err < 0) {
@@ -1367,25 +1369,24 @@ static int smi_wait_ready(struct mvneta_port *pp)
 }
 
 /*
- * smi_reg_read - miiphy_read callback function.
+ * mvneta_mdio_read - miiphy_read callback function.
  *
  * Returns 16bit phy register value, or 0xffff on error
  */
-static int smi_reg_read(const char *devname, u8 phy_adr, u8 reg_ofs, u16 *data)
+static int mvneta_mdio_read(struct mii_dev *bus, int addr, int devad, int reg)
 {
-	struct eth_device *dev = eth_get_dev_by_name(devname);
-	struct mvneta_port *pp = dev->priv;
+	struct mvneta_port *pp = bus->priv;
 	u32 smi_reg;
 	u32 timeout;
 
 	/* check parameters */
-	if (phy_adr > MVNETA_PHY_ADDR_MASK) {
-		printf("Error: Invalid PHY address %d\n", phy_adr);
+	if (addr > MVNETA_PHY_ADDR_MASK) {
+		printf("Error: Invalid PHY address %d\n", addr);
 		return -EFAULT;
 	}
 
-	if (reg_ofs > MVNETA_PHY_REG_MASK) {
-		printf("Err: Invalid register offset %d\n", reg_ofs);
+	if (reg > MVNETA_PHY_REG_MASK) {
+		printf("Err: Invalid register offset %d\n", reg);
 		return -EFAULT;
 	}
 
@@ -1394,14 +1395,14 @@ static int smi_reg_read(const char *devname, u8 phy_adr, u8 reg_ofs, u16 *data)
 		return -EFAULT;
 
 	/* fill the phy address and regiser offset and read opcode */
-	smi_reg = (phy_adr << MVNETA_SMI_DEV_ADDR_OFFS)
-		| (reg_ofs << MVNETA_SMI_REG_ADDR_OFFS)
+	smi_reg = (addr << MVNETA_SMI_DEV_ADDR_OFFS)
+		| (reg << MVNETA_SMI_REG_ADDR_OFFS)
 		| MVNETA_SMI_OPCODE_READ;
 
 	/* write the smi register */
 	mvreg_write(pp, MVNETA_SMI, smi_reg);
 
-	/*wait till read value is ready */
+	/* wait till read value is ready */
 	timeout = MVNETA_SMI_TIMEOUT;
 
 	do {
@@ -1417,31 +1418,29 @@ static int smi_reg_read(const char *devname, u8 phy_adr, u8 reg_ofs, u16 *data)
 	for (timeout = 0; timeout < MVNETA_SMI_TIMEOUT; timeout++)
 		;
 
-	*data = (u16)(mvreg_read(pp, MVNETA_SMI) & MVNETA_SMI_DATA_MASK);
-
-	return 0;
+	return mvreg_read(pp, MVNETA_SMI) & MVNETA_SMI_DATA_MASK;
 }
 
 /*
- * smi_reg_write - imiiphy_write callback function.
+ * mvneta_mdio_write - miiphy_write callback function.
  *
  * Returns 0 if write succeed, -EINVAL on bad parameters
  * -ETIME on timeout
  */
-static int smi_reg_write(const char *devname, u8 phy_adr, u8 reg_ofs, u16 data)
+static int mvneta_mdio_write(struct mii_dev *bus, int addr, int devad, int reg,
+			     u16 value)
 {
-	struct eth_device *dev = eth_get_dev_by_name(devname);
-	struct mvneta_port *pp = dev->priv;
+	struct mvneta_port *pp = bus->priv;
 	u32 smi_reg;
 
 	/* check parameters */
-	if (phy_adr > MVNETA_PHY_ADDR_MASK) {
-		printf("Error: Invalid PHY address %d\n", phy_adr);
+	if (addr > MVNETA_PHY_ADDR_MASK) {
+		printf("Error: Invalid PHY address %d\n", addr);
 		return -EFAULT;
 	}
 
-	if (reg_ofs > MVNETA_PHY_REG_MASK) {
-		printf("Err: Invalid register offset %d\n", reg_ofs);
+	if (reg > MVNETA_PHY_REG_MASK) {
+		printf("Err: Invalid register offset %d\n", reg);
 		return -EFAULT;
 	}
 
@@ -1450,9 +1449,9 @@ static int smi_reg_write(const char *devname, u8 phy_adr, u8 reg_ofs, u16 data)
 		return -EFAULT;
 
 	/* fill the phy addr and reg offset and write opcode and data */
-	smi_reg = (data << MVNETA_SMI_DATA_OFFS);
-	smi_reg |= (phy_adr << MVNETA_SMI_DEV_ADDR_OFFS)
-		| (reg_ofs << MVNETA_SMI_REG_ADDR_OFFS);
+	smi_reg = value << MVNETA_SMI_DATA_OFFS;
+	smi_reg |= (addr << MVNETA_SMI_DEV_ADDR_OFFS)
+		| (reg << MVNETA_SMI_REG_ADDR_OFFS);
 	smi_reg &= ~MVNETA_SMI_OPCODE_READ;
 
 	/* write the smi register */
@@ -1461,9 +1460,9 @@ static int smi_reg_write(const char *devname, u8 phy_adr, u8 reg_ofs, u16 data)
 	return 0;
 }
 
-static int mvneta_init_u_boot(struct eth_device *dev, bd_t *bis)
+static int mvneta_start(struct udevice *dev)
 {
-	struct mvneta_port *pp = dev->priv;
+	struct mvneta_port *pp = dev_get_priv(dev);
 	struct phy_device *phydev;
 
 	mvneta_port_power_up(pp, pp->phy_interface);
@@ -1483,7 +1482,7 @@ static int mvneta_init_u_boot(struct eth_device *dev, bd_t *bis)
 		}
 
 		/* Full init on first call */
-		mvneta_probe(dev);
+		mvneta_init(dev);
 		pp->init = 1;
 	} else {
 		/* Upon all following calls, this is enough */
@@ -1494,9 +1493,9 @@ static int mvneta_init_u_boot(struct eth_device *dev, bd_t *bis)
 	return 0;
 }
 
-static int mvneta_send(struct eth_device *dev, void *ptr, int len)
+static int mvneta_send(struct udevice *dev, void *packet, int length)
 {
-	struct mvneta_port *pp = dev->priv;
+	struct mvneta_port *pp = dev_get_priv(dev);
 	struct mvneta_tx_queue *txq = &pp->txqs[0];
 	struct mvneta_tx_desc *tx_desc;
 	int sent_desc;
@@ -1505,9 +1504,9 @@ static int mvneta_send(struct eth_device *dev, void *ptr, int len)
 	/* Get a descriptor for the first part of the packet */
 	tx_desc = mvneta_txq_next_desc_get(txq);
 
-	tx_desc->buf_phys_addr = (u32)ptr;
-	tx_desc->data_size = len;
-	flush_dcache_range((u32)ptr, (u32)ptr + len);
+	tx_desc->buf_phys_addr = (u32)packet;
+	tx_desc->data_size = length;
+	flush_dcache_range((u32)packet, (u32)packet + length);
 
 	/* First and Last descriptor */
 	tx_desc->command = MVNETA_TX_L4_CSUM_NOT | MVNETA_TXD_FLZ_DESC;
@@ -1525,28 +1524,25 @@ static int mvneta_send(struct eth_device *dev, void *ptr, int len)
 
 	/* txDone has increased - hw sent packet */
 	mvneta_txq_sent_desc_dec(pp, txq, sent_desc);
-	return 0;
 
 	return 0;
 }
 
-static int mvneta_recv(struct eth_device *dev)
+static int mvneta_recv(struct udevice *dev, int flags, uchar **packetp)
 {
-	struct mvneta_port *pp = dev->priv;
+	struct mvneta_port *pp = dev_get_priv(dev);
 	int rx_done;
-	int packets_done;
 	struct mvneta_rx_queue *rxq;
+	int rx_bytes = 0;
 
 	/* get rx queue */
 	rxq = mvneta_rxq_handle_get(pp, rxq_def);
 	rx_done = mvneta_rxq_busy_desc_num_get(pp, rxq);
-	packets_done = rx_done;
 
-	while (packets_done--) {
+	if (rx_done) {
 		struct mvneta_rx_desc *rx_desc;
 		unsigned char *data;
 		u32 rx_status;
-		int rx_bytes;
 
 		/*
 		 * No cache invalidation needed here, since the desc's are
@@ -1559,7 +1555,7 @@ static int mvneta_recv(struct eth_device *dev)
 		    (rx_status & MVNETA_RXD_ERR_SUMMARY)) {
 			mvneta_rx_error(pp, rx_desc);
 			/* leave the descriptor untouched */
-			continue;
+			return -EIO;
 		}
 
 		/* 2 bytes for marvell header. 4 bytes for crc */
@@ -1571,40 +1567,24 @@ static int mvneta_recv(struct eth_device *dev)
 		 * No cache invalidation needed here, since the rx_buffer's are
 		 * located in a uncached memory region
 		 */
-		net_process_received_packet(data, rx_bytes);
-	}
+		*packetp = data;
 
-	/* Update rxq management counters */
-	if (rx_done)
 		mvneta_rxq_desc_num_update(pp, rxq, rx_done, rx_done);
+	}
 
-	return 0;
-}
-
-static void mvneta_halt(struct eth_device *dev)
-{
-	struct mvneta_port *pp = dev->priv;
-
-	mvneta_port_down(pp);
-	mvneta_port_disable(pp);
+	return rx_bytes;
 }
 
-int mvneta_initialize(bd_t *bis, int base_addr, int devnum, int phy_addr)
+static int mvneta_probe(struct udevice *dev)
 {
-	struct eth_device *dev;
-	struct mvneta_port *pp;
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	struct mvneta_port *pp = dev_get_priv(dev);
+	void *blob = (void *)gd->fdt_blob;
+	int node = dev->of_offset;
+	struct mii_dev *bus;
+	unsigned long addr;
 	void *bd_space;
 
-	dev = calloc(1, sizeof(*dev));
-	if (dev == NULL)
-		return -ENOMEM;
-
-	pp = calloc(1, sizeof(*pp));
-	if (pp == NULL)
-		return -ENOMEM;
-
-	dev->priv = pp;
-
 	/*
 	 * Allocate buffer area for descs and rx_buffers. This is only
 	 * done once for all interfaces. As only one interface can
@@ -1625,28 +1605,82 @@ int mvneta_initialize(bd_t *bis, int base_addr, int devnum, int phy_addr)
 			 MVNETA_MAX_RXD * sizeof(struct mvneta_rx_desc));
 	}
 
-	sprintf(dev->name, "neta%d", devnum);
+	pp->base = (void __iomem *)pdata->iobase;
 
-	pp->base = (void __iomem *)base_addr;
-	dev->iobase = base_addr;
-	dev->init = mvneta_init_u_boot;
-	dev->halt = mvneta_halt;
-	dev->send = mvneta_send;
-	dev->recv = mvneta_recv;
-	dev->write_hwaddr = NULL;
+	/* Configure MBUS address windows */
+	mvneta_conf_mbus_windows(pp);
 
-	/*
-	 * The PHY interface type is configured via the
-	 * board specific CONFIG_SYS_NETA_INTERFACE_TYPE
-	 * define.
-	 */
-	pp->phy_interface = CONFIG_SYS_NETA_INTERFACE_TYPE;
+	/* PHY interface is already decoded in mvneta_ofdata_to_platdata() */
+	pp->phy_interface = pdata->phy_interface;
+
+	/* Now read phyaddr from DT */
+	addr = fdtdec_get_int(blob, node, "phy", 0);
+	addr = fdt_node_offset_by_phandle(blob, addr);
+	pp->phyaddr = fdtdec_get_int(blob, addr, "reg", 0);
+
+	bus = mdio_alloc();
+	if (!bus) {
+		printf("Failed to allocate MDIO bus\n");
+		return -ENOMEM;
+	}
+
+	bus->read = mvneta_mdio_read;
+	bus->write = mvneta_mdio_write;
+	snprintf(bus->name, sizeof(bus->name), dev->name);
+	bus->priv = (void *)pp;
+	pp->bus = bus;
 
-	eth_register(dev);
+	return mdio_register(bus);
+}
 
-	pp->phyaddr = phy_addr;
-	miiphy_register(dev->name, smi_reg_read, smi_reg_write);
-	pp->bus = miiphy_get_dev_by_name(dev->name);
+static void mvneta_stop(struct udevice *dev)
+{
+	struct mvneta_port *pp = dev_get_priv(dev);
 
-	return 1;
+	mvneta_port_down(pp);
+	mvneta_port_disable(pp);
 }
+
+static const struct eth_ops mvneta_ops = {
+	.start		= mvneta_start,
+	.send		= mvneta_send,
+	.recv		= mvneta_recv,
+	.stop		= mvneta_stop,
+};
+
+static int mvneta_ofdata_to_platdata(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	const char *phy_mode;
+
+	pdata->iobase = dev_get_addr(dev);
+
+	/* Get phy-mode / phy_interface from DT */
+	pdata->phy_interface = -1;
+	phy_mode = fdt_getprop(gd->fdt_blob, dev->of_offset, "phy-mode", NULL);
+	if (phy_mode)
+		pdata->phy_interface = phy_get_interface_by_name(phy_mode);
+	if (pdata->phy_interface == -1) {
+		debug("%s: Invalid PHY interface '%s'\n", __func__, phy_mode);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static const struct udevice_id mvneta_ids[] = {
+	{ .compatible = "marvell,armada-370-neta" },
+	{ .compatible = "marvell,armada-xp-neta" },
+	{ }
+};
+
+U_BOOT_DRIVER(mvneta) = {
+	.name	= "mvneta",
+	.id	= UCLASS_ETH,
+	.of_match = mvneta_ids,
+	.ofdata_to_platdata = mvneta_ofdata_to_platdata,
+	.probe	= mvneta_probe,
+	.ops	= &mvneta_ops,
+	.priv_auto_alloc_size = sizeof(struct mvneta_port),
+	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
+};
diff --git a/drivers/pci/pci_auto_old.c b/drivers/pci/pci_auto_old.c
index 9126f78b890b199f6aab2c6ac0927160e49e7263..edc9a7b3c1704eb7d222a1c1ee6ce5fd3db55726 100644
--- a/drivers/pci/pci_auto_old.c
+++ b/drivers/pci/pci_auto_old.c
@@ -101,11 +101,11 @@ void pciauto_setup_device(struct pci_controller *hose,
 				bar_res = prefetch;
 			else
 				bar_res = mem;
-#endif
 
 			debug("PCI Autoconfig: BAR %d, %s, size=0x%llx, ",
 			      bar_nr, bar_res == prefetch ? "Prf" : "Mem",
 			      (unsigned long long)bar_size);
+#endif
 		}
 
 #ifndef CONFIG_PCI_ENUM_ONLY
diff --git a/drivers/pci/pci_mvebu.c b/drivers/pci/pci_mvebu.c
index fd2744dbd4e97c4dec0f9a0149c7fd7dc054f329..4eedfe1cbb56e5e9289f282b9e2b8a20e6cd4808 100644
--- a/drivers/pci/pci_mvebu.c
+++ b/drivers/pci/pci_mvebu.c
@@ -155,6 +155,14 @@ static void mvebu_get_port_lane(struct mvebu_pcie *pcie, int pex_idx,
 }
 #endif
 
+static int mvebu_pex_unit_is_x4(int pex_idx)
+{
+	int pex_unit = pex_idx < 9 ? pex_idx >> 2 : 3;
+	u32 mask = (0x0f << (pex_unit * 8));
+
+	return (readl(COMPHY_REFCLK_ALIGNMENT) & mask) == mask;
+}
+
 static inline bool mvebu_pcie_link_up(struct mvebu_pcie *pcie)
 {
 	u32 val;
@@ -419,5 +427,11 @@ void pci_init_board(void)
 		writel(0, pcie->base + PCIE_BAR_HI_OFF(0));
 
 		bus = hose->last_busno + 1;
+
+		/* need to skip more for X4 links, otherwise scan will hang */
+		if (mvebu_soc_family() == MVEBU_SOC_AXP) {
+			if (mvebu_pex_unit_is_x4(i))
+				i += 3;
+		}
 	}
 }
diff --git a/drivers/spi/kirkwood_spi.c b/drivers/spi/kirkwood_spi.c
index e7b0982fb654681e4b9650d7ce8fe9a9c23d8acd..7890796b36bf09ecdf34442f4456de94b82b3a7c 100644
--- a/drivers/spi/kirkwood_spi.c
+++ b/drivers/spi/kirkwood_spi.c
@@ -9,6 +9,7 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <malloc.h>
 #include <spi.h>
 #include <asm/io.h>
@@ -18,6 +19,83 @@
 #endif
 #include <asm/arch-mvebu/spi.h>
 
+static void _spi_cs_activate(struct kwspi_registers *reg)
+{
+	setbits_le32(&reg->ctrl, KWSPI_CSN_ACT);
+}
+
+static void _spi_cs_deactivate(struct kwspi_registers *reg)
+{
+	clrbits_le32(&reg->ctrl, KWSPI_CSN_ACT);
+}
+
+static int _spi_xfer(struct kwspi_registers *reg, unsigned int bitlen,
+		     const void *dout, void *din, unsigned long flags)
+{
+	unsigned int tmpdout, tmpdin;
+	int tm, isread = 0;
+
+	debug("spi_xfer: dout %p din %p bitlen %u\n", dout, din, bitlen);
+
+	if (flags & SPI_XFER_BEGIN)
+		_spi_cs_activate(reg);
+
+	/*
+	 * handle data in 8-bit chunks
+	 * TBD: 2byte xfer mode to be enabled
+	 */
+	clrsetbits_le32(&reg->cfg, KWSPI_XFERLEN_MASK, KWSPI_XFERLEN_1BYTE);
+
+	while (bitlen > 4) {
+		debug("loopstart bitlen %d\n", bitlen);
+		tmpdout = 0;
+
+		/* Shift data so it's msb-justified */
+		if (dout)
+			tmpdout = *(u32 *)dout & 0xff;
+
+		clrbits_le32(&reg->irq_cause, KWSPI_SMEMRDIRQ);
+		writel(tmpdout, &reg->dout);	/* Write the data out */
+		debug("*** spi_xfer: ... %08x written, bitlen %d\n",
+		      tmpdout, bitlen);
+
+		/*
+		 * Wait for SPI transmit to get out
+		 * or time out (1 second = 1000 ms)
+		 * The NE event must be read and cleared first
+		 */
+		for (tm = 0, isread = 0; tm < KWSPI_TIMEOUT; ++tm) {
+			if (readl(&reg->irq_cause) & KWSPI_SMEMRDIRQ) {
+				isread = 1;
+				tmpdin = readl(&reg->din);
+				debug("spi_xfer: din %p..%08x read\n",
+				      din, tmpdin);
+
+				if (din) {
+					*((u8 *)din) = (u8)tmpdin;
+					din += 1;
+				}
+				if (dout)
+					dout += 1;
+				bitlen -= 8;
+			}
+			if (isread)
+				break;
+		}
+		if (tm >= KWSPI_TIMEOUT)
+			printf("*** spi_xfer: Time out during SPI transfer\n");
+
+		debug("loopend bitlen %d\n", bitlen);
+	}
+
+	if (flags & SPI_XFER_END)
+		_spi_cs_deactivate(reg);
+
+	return 0;
+}
+
+#ifndef CONFIG_DM_SPI
+
 static struct kwspi_registers *spireg =
 	(struct kwspi_registers *)MVEBU_SPI_BASE;
 
@@ -147,76 +225,109 @@ void spi_init(void)
 
 void spi_cs_activate(struct spi_slave *slave)
 {
-	setbits_le32(&spireg->ctrl, KWSPI_CSN_ACT);
+	_spi_cs_activate(spireg);
 }
 
 void spi_cs_deactivate(struct spi_slave *slave)
 {
-	clrbits_le32(&spireg->ctrl, KWSPI_CSN_ACT);
+	_spi_cs_deactivate(spireg);
 }
 
-int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
-	     void *din, unsigned long flags)
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
+	     const void *dout, void *din, unsigned long flags)
 {
-	unsigned int tmpdout, tmpdin;
-	int tm, isread = 0;
+	return _spi_xfer(spireg, bitlen, dout, din, flags);
+}
 
-	debug("spi_xfer: slave %u:%u dout %p din %p bitlen %u\n",
-	      slave->bus, slave->cs, dout, din, bitlen);
+#else
 
-	if (flags & SPI_XFER_BEGIN)
-		spi_cs_activate(slave);
+/* Here now the DM part */
 
-	/*
-	 * handle data in 8-bit chunks
-	 * TBD: 2byte xfer mode to be enabled
-	 */
-	clrsetbits_le32(&spireg->cfg, KWSPI_XFERLEN_MASK, KWSPI_XFERLEN_1BYTE);
+struct mvebu_spi_platdata {
+	struct kwspi_registers *spireg;
+};
 
-	while (bitlen > 4) {
-		debug("loopstart bitlen %d\n", bitlen);
-		tmpdout = 0;
+struct mvebu_spi_priv {
+	struct kwspi_registers *spireg;
+};
 
-		/* Shift data so it's msb-justified */
-		if (dout)
-			tmpdout = *(u32 *)dout & 0xff;
+static int mvebu_spi_set_speed(struct udevice *bus, uint hz)
+{
+	struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
+	struct kwspi_registers *reg = plat->spireg;
+	u32 data;
 
-		clrbits_le32(&spireg->irq_cause, KWSPI_SMEMRDIRQ);
-		writel(tmpdout, &spireg->dout);	/* Write the data out */
-		debug("*** spi_xfer: ... %08x written, bitlen %d\n",
-		      tmpdout, bitlen);
+	/* calculate spi clock prescaller using max_hz */
+	data = ((CONFIG_SYS_TCLK / 2) / hz) + 0x10;
+	data = data < KWSPI_CLKPRESCL_MIN ? KWSPI_CLKPRESCL_MIN : data;
+	data = data > KWSPI_CLKPRESCL_MASK ? KWSPI_CLKPRESCL_MASK : data;
 
-		/*
-		 * Wait for SPI transmit to get out
-		 * or time out (1 second = 1000 ms)
-		 * The NE event must be read and cleared first
-		 */
-		for (tm = 0, isread = 0; tm < KWSPI_TIMEOUT; ++tm) {
-			if (readl(&spireg->irq_cause) & KWSPI_SMEMRDIRQ) {
-				isread = 1;
-				tmpdin = readl(&spireg->din);
-				debug("spi_xfer: din %p..%08x read\n",
-				      din, tmpdin);
+	/* program spi clock prescaler using max_hz */
+	writel(KWSPI_ADRLEN_3BYTE | data, &reg->cfg);
+	debug("data = 0x%08x\n", data);
 
-				if (din) {
-					*((u8 *)din) = (u8)tmpdin;
-					din += 1;
-				}
-				if (dout)
-					dout += 1;
-				bitlen -= 8;
-			}
-			if (isread)
-				break;
-		}
-		if (tm >= KWSPI_TIMEOUT)
-			printf("*** spi_xfer: Time out during SPI transfer\n");
+	return 0;
+}
 
-		debug("loopend bitlen %d\n", bitlen);
-	}
+static int mvebu_spi_set_mode(struct udevice *bus, uint mode)
+{
+	return 0;
+}
 
-	if (flags & SPI_XFER_END)
-		spi_cs_deactivate(slave);
+static int mvebu_spi_xfer(struct udevice *dev, unsigned int bitlen,
+			  const void *dout, void *din, unsigned long flags)
+{
+	struct udevice *bus = dev->parent;
+	struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
+
+	return _spi_xfer(plat->spireg, bitlen, dout, din, flags);
+}
+
+static int mvebu_spi_probe(struct udevice *bus)
+{
+	struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
+	struct kwspi_registers *reg = plat->spireg;
+
+	writel(KWSPI_SMEMRDY, &reg->ctrl);
+	writel(KWSPI_SMEMRDIRQ, &reg->irq_cause);
+	writel(KWSPI_IRQMASK, &reg->irq_mask);
+
+	return 0;
+}
+
+static int mvebu_spi_ofdata_to_platdata(struct udevice *bus)
+{
+	struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
+
+	plat->spireg = (struct kwspi_registers *)dev_get_addr(bus);
 
 	return 0;
 }
+
+static const struct dm_spi_ops mvebu_spi_ops = {
+	.xfer		= mvebu_spi_xfer,
+	.set_speed	= mvebu_spi_set_speed,
+	.set_mode	= mvebu_spi_set_mode,
+	/*
+	 * cs_info is not needed, since we require all chip selects to be
+	 * in the device tree explicitly
+	 */
+};
+
+static const struct udevice_id mvebu_spi_ids[] = {
+	{ .compatible = "marvell,armada-380-spi" },
+	{ .compatible = "marvell,armada-xp-spi" },
+	{ }
+};
+
+U_BOOT_DRIVER(mvebu_spi) = {
+	.name = "mvebu_spi",
+	.id = UCLASS_SPI,
+	.of_match = mvebu_spi_ids,
+	.ops = &mvebu_spi_ops,
+	.ofdata_to_platdata = mvebu_spi_ofdata_to_platdata,
+	.platdata_auto_alloc_size = sizeof(struct mvebu_spi_platdata),
+	.priv_auto_alloc_size = sizeof(struct mvebu_spi_priv),
+	.probe = mvebu_spi_probe,
+};
+#endif
diff --git a/include/configs/clearfog.h b/include/configs/clearfog.h
new file mode 100644
index 0000000000000000000000000000000000000000..f0de827fd26d86746ea9a4582af7dc68d77b671d
--- /dev/null
+++ b/include/configs/clearfog.h
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2015 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _CONFIG_CLEARFOG_H
+#define _CONFIG_CLEARFOG_H
+
+/*
+ * High Level Configuration Options (easy to change)
+ */
+
+#define CONFIG_DISPLAY_BOARDINFO_LATE
+
+/*
+ * TEXT_BASE needs to be below 16MiB, since this area is scrubbed
+ * for DDR ECC byte filling in the SPL before loading the main
+ * U-Boot into it.
+ */
+#define	CONFIG_SYS_TEXT_BASE	0x00800000
+#define CONFIG_SYS_TCLK		250000000	/* 250MHz */
+
+/*
+ * Commands configuration
+ */
+#define CONFIG_SYS_NO_FLASH		/* Declare no flash (NOR/SPI) */
+#define CONFIG_CMD_BOOTZ
+#define CONFIG_CMD_CACHE
+#define CONFIG_CMD_DHCP
+#define CONFIG_CMD_ENV
+#define CONFIG_CMD_EXT2
+#define CONFIG_CMD_EXT4
+#define CONFIG_CMD_FAT
+#define CONFIG_CMD_FS_GENERIC
+#define CONFIG_CMD_I2C
+#define CONFIG_CMD_MMC
+#define CONFIG_CMD_PCI
+#define CONFIG_CMD_PING
+#define CONFIG_CMD_SF
+#define CONFIG_CMD_SPI
+#define CONFIG_CMD_TFTPPUT
+#define CONFIG_CMD_TIME
+
+/* I2C */
+#define CONFIG_SYS_I2C
+#define CONFIG_SYS_I2C_MVTWSI
+#define CONFIG_I2C_MVTWSI_BASE0		MVEBU_TWSI_BASE
+#define CONFIG_SYS_I2C_SLAVE		0x0
+#define CONFIG_SYS_I2C_SPEED		100000
+
+/* SPI NOR flash default params, used by sf commands */
+#define CONFIG_SF_DEFAULT_SPEED		1000000
+#define CONFIG_SF_DEFAULT_MODE		SPI_MODE_3
+#define CONFIG_SPI_FLASH_STMICRO
+
+/*
+ * SDIO/MMC Card Configuration
+ */
+#define CONFIG_MMC
+#define CONFIG_MMC_SDMA
+#define CONFIG_GENERIC_MMC
+#define CONFIG_SDHCI
+#define CONFIG_MV_SDHCI
+#define CONFIG_SYS_MMC_BASE		MVEBU_SDIO_BASE
+
+/* Partition support */
+#define CONFIG_DOS_PARTITION
+#define CONFIG_EFI_PARTITION
+
+/* Additional FS support/configuration */
+#define CONFIG_SUPPORT_VFAT
+
+/* USB/EHCI configuration */
+#define CONFIG_EHCI_IS_TDI
+
+#define CONFIG_ENV_MIN_ENTRIES		128
+
+/* Environment in MMC */
+#define CONFIG_ENV_IS_IN_MMC
+#define CONFIG_SYS_MMC_ENV_DEV		0
+#define CONFIG_ENV_SECT_SIZE		0x200
+#define CONFIG_ENV_SIZE			0x10000
+/*
+ * For SD - reserve 1 LBA for MBR + 1M for u-boot image. The MMC/eMMC
+ * boot image starts @ LBA-0.
+ * As result in MMC/eMMC case it will be a 1 sector gap between u-boot
+ * image and environment
+ */
+#define CONFIG_ENV_OFFSET		0xf0000
+#define CONFIG_ENV_ADDR			CONFIG_ENV_OFFSET
+
+#define CONFIG_PHY_MARVELL		/* there is a marvell phy */
+#define PHY_ANEG_TIMEOUT	8000	/* PHY needs a longer aneg time */
+
+/* PCIe support */
+#ifndef CONFIG_SPL_BUILD
+#define CONFIG_PCI
+#define CONFIG_PCI_MVEBU
+#define CONFIG_PCI_PNP
+#define CONFIG_PCI_SCAN_SHOW
+#endif
+
+#define CONFIG_SYS_CONSOLE_INFO_QUIET	/* don't print console @ startup */
+#define CONFIG_SYS_ALT_MEMTEST
+
+/* Keep device tree and initrd in lower memory so the kernel can access them */
+#define CONFIG_EXTRA_ENV_SETTINGS	\
+	"fdt_high=0x10000000\0"		\
+	"initrd_high=0x10000000\0"
+
+/* SPL */
+/*
+ * Select the boot device here
+ *
+ * Currently supported are:
+ * SPL_BOOT_SPI_NOR_FLASH	- Booting via SPI NOR flash
+ * SPL_BOOT_SDIO_MMC_CARD	- Booting via SDIO/MMC card (partition 1)
+ */
+#define SPL_BOOT_SPI_NOR_FLASH		1
+#define SPL_BOOT_SDIO_MMC_CARD		2
+#define CONFIG_SPL_BOOT_DEVICE		SPL_BOOT_SDIO_MMC_CARD
+
+/* Defines for SPL */
+#define CONFIG_SPL_FRAMEWORK
+#define CONFIG_SPL_SIZE			(140 << 10)
+#define CONFIG_SPL_TEXT_BASE		0x40000030
+#define CONFIG_SPL_MAX_SIZE		(CONFIG_SPL_SIZE - 0x0030)
+
+#define CONFIG_SPL_BSS_START_ADDR	(0x40000000 + CONFIG_SPL_SIZE)
+#define CONFIG_SPL_BSS_MAX_SIZE		(16 << 10)
+
+#ifdef CONFIG_SPL_BUILD
+#define CONFIG_SYS_MALLOC_SIMPLE
+#endif
+
+#define CONFIG_SPL_STACK		(0x40000000 + ((192 - 16) << 10))
+#define CONFIG_SPL_BOOTROM_SAVE		(CONFIG_SPL_STACK + 4)
+
+#define CONFIG_SPL_LIBCOMMON_SUPPORT
+#define CONFIG_SPL_LIBGENERIC_SUPPORT
+#define CONFIG_SPL_SERIAL_SUPPORT
+#define CONFIG_SPL_I2C_SUPPORT
+
+#if CONFIG_SPL_BOOT_DEVICE == SPL_BOOT_SPI_NOR_FLASH
+/* SPL related SPI defines */
+#define CONFIG_SPL_SPI_SUPPORT
+#define CONFIG_SPL_SPI_FLASH_SUPPORT
+#define CONFIG_SPL_SPI_LOAD
+#define CONFIG_SPL_SPI_BUS		0
+#define CONFIG_SPL_SPI_CS		0
+#define CONFIG_SYS_SPI_U_BOOT_OFFS	0x20000
+#define CONFIG_SYS_U_BOOT_OFFS		CONFIG_SYS_SPI_U_BOOT_OFFS
+#endif
+
+#if CONFIG_SPL_BOOT_DEVICE == SPL_BOOT_SDIO_MMC_CARD
+/* SPL related MMC defines */
+#define CONFIG_SPL_MMC_SUPPORT
+#define CONFIG_SPL_LIBDISK_SUPPORT
+#define CONFIG_SYS_MMC_U_BOOT_OFFS		(160 << 10)
+#define CONFIG_SYS_U_BOOT_OFFS			CONFIG_SYS_MMC_U_BOOT_OFFS
+#define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR	((CONFIG_SYS_U_BOOT_OFFS / 512)\
+						 + 1)
+#define CONFIG_SYS_U_BOOT_MAX_SIZE_SECTORS	((512 << 10) / 512) /* 512KiB */
+#ifdef CONFIG_SPL_BUILD
+#define CONFIG_FIXED_SDHCI_ALIGNED_BUFFER	0x00180000	/* in SDRAM */
+#endif
+#endif
+
+/*
+ * mv-common.h should be defined after CMD configs since it used them
+ * to enable certain macros
+ */
+#include "mv-common.h"
+
+#endif /* _CONFIG_CLEARFOG_H */
diff --git a/include/configs/db-88f6820-gp.h b/include/configs/db-88f6820-gp.h
index 3673e5e3687f3599c80fe663e123f2fd4e90efc2..ef14132b89ed685fb177b1cc2cc9be53b412232a 100644
--- a/include/configs/db-88f6820-gp.h
+++ b/include/configs/db-88f6820-gp.h
@@ -10,15 +10,7 @@
 /*
  * High Level Configuration Options (easy to change)
  */
-#define CONFIG_ARMADA_XP		/* SOC Family Name */
-#define CONFIG_ARMADA_38X
-#define CONFIG_DB_88F6820_GP		/* Board target name for DDR training */
 
-#define CONFIG_SYS_L2_PL310
-
-#ifdef CONFIG_SPL_BUILD
-#define CONFIG_SKIP_LOWLEVEL_INIT	/* disable board lowlevel_init */
-#endif
 #define CONFIG_DISPLAY_BOARDINFO_LATE
 
 /*
@@ -99,16 +91,15 @@
 #define CONFIG_ENV_SECT_SIZE		(256 << 10) /* 256KiB sectors */
 
 #define CONFIG_PHY_MARVELL		/* there is a marvell phy */
-#define CONFIG_PHY_ADDR			{ 1, 0 }
-#define CONFIG_SYS_NETA_INTERFACE_TYPE	PHY_INTERFACE_MODE_RGMII
 #define PHY_ANEG_TIMEOUT	8000	/* PHY needs a longer aneg time */
 
 /* PCIe support */
+#ifndef CONFIG_SPL_BUILD
 #define CONFIG_PCI
 #define CONFIG_PCI_MVEBU
 #define CONFIG_PCI_PNP
 #define CONFIG_PCI_SCAN_SHOW
-#define CONFIG_E1000	/* enable Intel E1000 support for testing */
+#endif
 
 #define CONFIG_SYS_CONSOLE_INFO_QUIET	/* don't print console @ startup */
 #define CONFIG_SYS_ALT_MEMTEST
@@ -139,9 +130,9 @@
 #define CONFIG_SPL_BSS_START_ADDR	(0x40000000 + CONFIG_SPL_SIZE)
 #define CONFIG_SPL_BSS_MAX_SIZE		(16 << 10)
 
-#define CONFIG_SYS_SPL_MALLOC_START	(CONFIG_SPL_BSS_START_ADDR + \
-					 CONFIG_SPL_BSS_MAX_SIZE)
-#define CONFIG_SYS_SPL_MALLOC_SIZE	(16 << 10)
+#ifdef CONFIG_SPL_BUILD
+#define CONFIG_SYS_MALLOC_SIMPLE
+#endif
 
 #define CONFIG_SPL_STACK		(0x40000000 + ((192 - 16) << 10))
 #define CONFIG_SPL_BOOTROM_SAVE		(CONFIG_SPL_STACK + 4)
@@ -158,7 +149,7 @@
 #define CONFIG_SPL_SPI_LOAD
 #define CONFIG_SPL_SPI_BUS		0
 #define CONFIG_SPL_SPI_CS		0
-#define CONFIG_SYS_SPI_U_BOOT_OFFS	0x20000
+#define CONFIG_SYS_SPI_U_BOOT_OFFS	0x24000
 #define CONFIG_SYS_U_BOOT_OFFS		CONFIG_SYS_SPI_U_BOOT_OFFS
 #endif
 
@@ -176,10 +167,6 @@
 #endif
 #endif
 
-/* Enable DDR support in SPL (DDR3 training from Marvell bin_hdr) */
-#define CONFIG_SYS_MVEBU_DDR_A38X
-#define CONFIG_DDR3
-
 /*
  * mv-common.h should be defined after CMD configs since it used them
  * to enable certain macros
diff --git a/include/configs/db-mv784mp-gp.h b/include/configs/db-mv784mp-gp.h
index ab6e5a5bce19f741c38eaffc85ddf8df3456fd09..c8b03441855f0798fc18c6133d2dba298e942b24 100644
--- a/include/configs/db-mv784mp-gp.h
+++ b/include/configs/db-mv784mp-gp.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 Stefan Roese <sr@denx.de>
+ * Copyright (C) 2014-2015 Stefan Roese <sr@denx.de>
  *
  * SPDX-License-Identifier:	GPL-2.0+
  */
@@ -10,12 +10,8 @@
 /*
  * High Level Configuration Options (easy to change)
  */
-#define CONFIG_ARMADA_XP		/* SOC Family Name */
 #define CONFIG_DB_784MP_GP		/* Board target name for DDR training */
 
-#ifdef CONFIG_SPL_BUILD
-#define CONFIG_SKIP_LOWLEVEL_INIT	/* disable board lowlevel_init */
-#endif
 #define CONFIG_DISPLAY_BOARDINFO_LATE
 
 /*
@@ -30,13 +26,18 @@
  * Commands configuration
  */
 #define CONFIG_SYS_NO_FLASH		/* Declare no flash (NOR/SPI) */
+#define CONFIG_CMD_CACHE
 #define CONFIG_CMD_DHCP
 #define CONFIG_CMD_ENV
+#define CONFIG_CMD_EXT2
+#define CONFIG_CMD_EXT4
+#define CONFIG_CMD_FAT
+#define CONFIG_CMD_FS_GENERIC
 #define CONFIG_CMD_I2C
-#define CONFIG_CMD_IDE
 #define CONFIG_CMD_NAND
 #define CONFIG_CMD_PCI
 #define CONFIG_CMD_PING
+#define CONFIG_CMD_SATA
 #define CONFIG_CMD_SF
 #define CONFIG_CMD_SPI
 #define CONFIG_CMD_TFTPPUT
@@ -64,48 +65,29 @@
 #define CONFIG_ENV_SECT_SIZE		(64 << 10) /* 64KiB sectors */
 
 #define CONFIG_PHY_MARVELL		/* there is a marvell phy */
-#define CONFIG_PHY_ADDR			{ 0x10, 0x11, 0x12, 0x13 }
-#define CONFIG_SYS_NETA_INTERFACE_TYPE	PHY_INTERFACE_MODE_QSGMII
 #define PHY_ANEG_TIMEOUT	8000	/* PHY needs a longer aneg time */
-#define CONFIG_RESET_PHY_R
 
 #define CONFIG_SYS_CONSOLE_INFO_QUIET	/* don't print console @ startup */
 #define CONFIG_SYS_ALT_MEMTEST
 
 /* SATA support */
-#ifdef CONFIG_CMD_IDE
-#define __io
-#define CONFIG_IDE_PREINIT
-#define CONFIG_MVSATA_IDE
-
-/* Needs byte-swapping for ATA data register */
-#define CONFIG_IDE_SWAP_IO
-
-#define CONFIG_SYS_ATA_REG_OFFSET	0x0100 /* Offset for register access */
-#define CONFIG_SYS_ATA_DATA_OFFSET	0x0100 /* Offset for data I/O */
-#define CONFIG_SYS_ATA_ALT_OFFSET	0x0100
-
-/* Each 8-bit ATA register is aligned to a 4-bytes address */
-#define CONFIG_SYS_ATA_STRIDE		4
-
-/* CONFIG_CMD_IDE requires some #defines for ATA registers */
-#define CONFIG_SYS_IDE_MAXBUS		2
-#define CONFIG_SYS_IDE_MAXDEVICE	CONFIG_SYS_IDE_MAXBUS
-
-/* ATA registers base is at SATA controller base */
-#define CONFIG_SYS_ATA_BASE_ADDR	MVEBU_AXP_SATA_BASE
-#define CONFIG_SYS_ATA_IDE0_OFFSET	0x2000
-#define CONFIG_SYS_ATA_IDE1_OFFSET	0x4000
-
+#define CONFIG_SYS_SATA_MAX_DEVICE	2
+#define CONFIG_SATA_MV
+#define CONFIG_LIBATA
+#define CONFIG_LBA48
+#define CONFIG_EFI_PARTITION
 #define CONFIG_DOS_PARTITION
-#endif /* CONFIG_CMD_IDE */
+
+/* Additional FS support/configuration */
+#define CONFIG_SUPPORT_VFAT
 
 /* PCIe support */
+#ifndef CONFIG_SPL_BUILD
 #define CONFIG_PCI
 #define CONFIG_PCI_MVEBU
 #define CONFIG_PCI_PNP
 #define CONFIG_PCI_SCAN_SHOW
-#define CONFIG_E1000	/* enable Intel E1000 support for testing */
+#endif
 
 /* NAND */
 #define CONFIG_SYS_NAND_USE_FLASH_BBT
@@ -139,9 +121,9 @@
 #define CONFIG_SPL_BSS_START_ADDR	(0x40000000 + (128 << 10))
 #define CONFIG_SPL_BSS_MAX_SIZE		(16 << 10)
 
-#define CONFIG_SYS_SPL_MALLOC_START	(CONFIG_SPL_BSS_START_ADDR + \
-					 CONFIG_SPL_BSS_MAX_SIZE)
-#define CONFIG_SYS_SPL_MALLOC_SIZE	(16 << 10)
+#ifdef CONFIG_SPL_BUILD
+#define CONFIG_SYS_MALLOC_SIMPLE
+#endif
 
 #define CONFIG_SPL_STACK		(0x40000000 + ((192 - 16) << 10))
 #define CONFIG_SPL_BOOTROM_SAVE		(CONFIG_SPL_STACK + 4)
@@ -161,7 +143,7 @@
 #define CONFIG_SYS_U_BOOT_OFFS		CONFIG_SYS_SPI_U_BOOT_OFFS
 
 /* Enable DDR support in SPL (DDR3 training from Marvell bin_hdr) */
-#define CONFIG_SYS_MVEBU_DDR_AXP
 #define CONFIG_SPD_EEPROM		0x4e
+#define CONFIG_BOARD_ECC_SUPPORT	/* this board supports ECC */
 
 #endif /* _CONFIG_DB_MV7846MP_GP_H */
diff --git a/include/configs/ds414.h b/include/configs/ds414.h
new file mode 100644
index 0000000000000000000000000000000000000000..e3c7087a1fa009905f7a36d6ed7b017e4d64178d
--- /dev/null
+++ b/include/configs/ds414.h
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2014 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _CONFIG_SYNOLOGY_DS414_H
+#define _CONFIG_SYNOLOGY_DS414_H
+
+/*
+ * High Level Configuration Options (easy to change)
+ */
+#define CONFIG_DISPLAY_BOARDINFO_LATE
+
+/*
+ * TEXT_BASE needs to be below 16MiB, since this area is scrubbed
+ * for DDR ECC byte filling in the SPL before loading the main
+ * U-Boot into it.
+ */
+#define	CONFIG_SYS_TEXT_BASE	0x00800000
+#define CONFIG_SYS_TCLK		250000000	/* 250MHz */
+
+/*
+ * Commands configuration
+ */
+#define CONFIG_SYS_NO_FLASH		/* Declare no flash (NOR/SPI) */
+#define CONFIG_CMD_DHCP
+#define CONFIG_CMD_ENV
+#define CONFIG_CMD_I2C
+#define CONFIG_CMD_PING
+#define CONFIG_CMD_SF
+#define CONFIG_CMD_SPI
+#define CONFIG_CMD_TFTPPUT
+#define CONFIG_CMD_TIME
+#define CONFIG_CMD_USB
+
+/* I2C */
+#define CONFIG_SYS_I2C
+#define CONFIG_SYS_I2C_MVTWSI
+#define CONFIG_I2C_MVTWSI_BASE0		MVEBU_TWSI_BASE
+#define CONFIG_SYS_I2C_SLAVE		0x0
+#define CONFIG_SYS_I2C_SPEED		100000
+
+/* SPI NOR flash default params, used by sf commands */
+#define CONFIG_SF_DEFAULT_SPEED		1000000
+#define CONFIG_SF_DEFAULT_MODE		SPI_MODE_3
+
+/* Environment in SPI NOR flash */
+#define CONFIG_ENV_IS_IN_SPI_FLASH
+#define CONFIG_ENV_OFFSET		0x7E0000   /* RedBoot config partition in DTS */
+#define CONFIG_ENV_SIZE			(64 << 10) /* 64KiB */
+#define CONFIG_ENV_SECT_SIZE		(64 << 10) /* 64KiB sectors */
+
+#define CONFIG_PHY_MARVELL		/* there is a marvell phy */
+#define CONFIG_PHY_ADDR			{ 0x1, 0x0 }
+#define CONFIG_SYS_NETA_INTERFACE_TYPE	PHY_INTERFACE_MODE_RGMII
+
+#define CONFIG_SYS_ALT_MEMTEST
+
+/* PCIe support */
+#ifndef CONFIG_SPL_BUILD
+#define CONFIG_PCI
+#define CONFIG_CMD_PCI
+#define CONFIG_CMD_PCI_ENUM
+#define CONFIG_PCI_MVEBU
+#define CONFIG_PCI_SCAN_SHOW
+#endif
+
+/* USB/EHCI/XHCI configuration */
+
+#define CONFIG_DM_USB
+#define CONFIG_USB_MAX_CONTROLLER_COUNT 2
+
+/* FIXME: broken XHCI support
+ * Below defines should enable support for the two rear USB3 ports. Sadly, this
+ * does not work because:
+ * - xhci-pci seems to not support DM_USB, so with that enabled it is not
+ *   found.
+ * - USB init fails, controller does not respond in time */
+#if 0
+#undef CONFIG_DM_USB
+#define CONFIG_USB_XHCI
+#define CONFIG_USB_XHCI_PCI
+#define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS 2
+#endif
+
+#if !defined(CONFIG_USB_XHCI)
+#define CONFIG_USB_EHCI
+#define CONFIG_USB_EHCI_MARVELL
+#define CONFIG_EHCI_IS_TDI
+#endif
+
+/* why is this only defined in mv-common.h if CONFIG_DM is undefined? */
+#define CONFIG_USB_STORAGE
+#define CONFIG_DOS_PARTITION
+#define CONFIG_ISO_PARTITION
+#define CONFIG_SUPPORT_VFAT
+#define CONFIG_SYS_MVFS
+
+/*
+ * mv-common.h should be defined after CMD configs since it used them
+ * to enable certain macros
+ */
+#include "mv-common.h"
+
+/*
+ * Memory layout while starting into the bin_hdr via the
+ * BootROM:
+ *
+ * 0x4000.4000 - 0x4003.4000	headers space (192KiB)
+ * 0x4000.4030			bin_hdr start address
+ * 0x4003.4000 - 0x4004.7c00	BootROM memory allocations (15KiB)
+ * 0x4007.fffc			BootROM stack top
+ *
+ * The address space between 0x4007.fffc and 0x400f.fff is not locked in
+ * L2 cache thus cannot be used.
+ */
+
+/* SPL */
+/* Defines for SPL */
+#define CONFIG_SPL_FRAMEWORK
+#define CONFIG_SPL_TEXT_BASE		0x40004030
+#define CONFIG_SPL_MAX_SIZE		((128 << 10) - 0x4030)
+
+#define CONFIG_SPL_BSS_START_ADDR	(0x40000000 + (128 << 10))
+#define CONFIG_SPL_BSS_MAX_SIZE		(16 << 10)
+
+#ifdef CONFIG_SPL_BUILD
+#define CONFIG_SYS_MALLOC_SIMPLE
+#endif
+
+#define CONFIG_SPL_STACK		(0x40000000 + ((192 - 16) << 10))
+#define CONFIG_SPL_BOOTROM_SAVE		(CONFIG_SPL_STACK + 4)
+
+#define CONFIG_SPL_LIBCOMMON_SUPPORT
+#define CONFIG_SPL_LIBGENERIC_SUPPORT
+#define CONFIG_SPL_SERIAL_SUPPORT
+#define CONFIG_SPL_I2C_SUPPORT
+
+/* SPL related SPI defines */
+#define CONFIG_SPL_SPI_SUPPORT
+#define CONFIG_SPL_SPI_FLASH_SUPPORT
+#define CONFIG_SPL_SPI_LOAD
+#define CONFIG_SPL_SPI_BUS		0
+#define CONFIG_SPL_SPI_CS		0
+#define CONFIG_SYS_SPI_U_BOOT_OFFS	0x24000
+
+/* DS414 bus width is 32bits */
+#define CONFIG_DDR_32BIT
+
+/* Use random ethernet address if not configured */
+#define CONFIG_LIB_RAND
+#define CONFIG_NET_RANDOM_ETHADDR
+
+/* Default Environment */
+#define CONFIG_BOOTCOMMAND	"sf read ${loadaddr} 0xd0000 0x700000; bootm"
+#define CONFIG_BOOTARGS		"console=ttyS0,115200"
+#define CONFIG_LOADADDR		0x80000
+#undef CONFIG_PREBOOT		/* override preboot for USB and SPI flash init */
+#define CONFIG_PREBOOT		"usb start; sf probe"
+
+#endif /* _CONFIG_SYNOLOGY_DS414_H */
diff --git a/include/configs/maxbcm.h b/include/configs/maxbcm.h
index da49243ebfa679fa9ed0505e42fdb71e93edb0ce..43d7fd03a3402254f8706e4e1ee5afa43b139b79 100644
--- a/include/configs/maxbcm.h
+++ b/include/configs/maxbcm.h
@@ -10,10 +10,6 @@
 /*
  * High Level Configuration Options (easy to change)
  */
-#define CONFIG_ARMADA_XP		/* SOC Family Name */
-#ifdef CONFIG_SPL_BUILD
-#define CONFIG_SKIP_LOWLEVEL_INIT	/* disable board lowlevel_init */
-#endif
 #define CONFIG_DISPLAY_BOARDINFO_LATE
 
 /*
@@ -55,10 +51,7 @@
 #define CONFIG_ENV_SECT_SIZE		(64 << 10) /* 64KiB sectors */
 
 #define CONFIG_PHY_MARVELL		/* there is a marvell phy */
-#define CONFIG_PHY_ADDR			{ 0x0, 0x1, 0x2, 0x3 }
-#define CONFIG_SYS_NETA_INTERFACE_TYPE	PHY_INTERFACE_MODE_SGMII
 #define PHY_ANEG_TIMEOUT	8000	/* PHY needs a longer aneg time */
-#define CONFIG_RESET_PHY_R
 
 #define CONFIG_SYS_CONSOLE_INFO_QUIET	/* don't print console @ startup */
 #define CONFIG_SYS_ALT_MEMTEST
@@ -91,9 +84,9 @@
 #define CONFIG_SPL_BSS_START_ADDR	(0x40000000 + (128 << 10))
 #define CONFIG_SPL_BSS_MAX_SIZE		(16 << 10)
 
-#define CONFIG_SYS_SPL_MALLOC_START	(CONFIG_SPL_BSS_START_ADDR + \
-					 CONFIG_SPL_BSS_MAX_SIZE)
-#define CONFIG_SYS_SPL_MALLOC_SIZE	(16 << 10)
+#ifdef CONFIG_SPL_BUILD
+#define CONFIG_SYS_MALLOC_SIMPLE
+#endif
 
 #define CONFIG_SPL_STACK		(0x40000000 + ((192 - 16) << 10))
 #define CONFIG_SPL_BOOTROM_SAVE		(CONFIG_SPL_STACK + 4)
@@ -112,7 +105,7 @@
 #define CONFIG_SYS_SPI_U_BOOT_OFFS	0x20000
 
 /* Enable DDR support in SPL (DDR3 training from Marvell bin_hdr) */
-#define CONFIG_SYS_MVEBU_DDR_AXP
 #define CONFIG_DDR_FIXED_SIZE		(1 << 20)	/* 1GiB */
+#define CONFIG_BOARD_ECC_SUPPORT	/* this board supports ECC */
 
 #endif /* _CONFIG_DB_MV7846MP_GP_H */
diff --git a/tools/Makefile b/tools/Makefile
index d49e40dd56175962cebac31864f57e261ed42bde..1382b0562e569950f994a1e9e83f2d0652218804 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -156,7 +156,7 @@ ubsha1-objs := os_support.o ubsha1.o lib/sha1.o
 HOSTCFLAGS_ubsha1.o := -pedantic
 
 hostprogs-$(CONFIG_KIRKWOOD) += kwboot
-hostprogs-$(CONFIG_ARMADA_XP) += kwboot
+hostprogs-$(CONFIG_ARCH_MVEBU) += kwboot
 hostprogs-y += proftool
 hostprogs-$(CONFIG_STATIC_RELA) += relocate-rela
 
diff --git a/tools/kwboot.c b/tools/kwboot.c
index c5f4492b5f7ab3d4a3b1a609740316cebcb7dae5..905ade3b01236d11e4727e32a354c9d866ca618a 100644
--- a/tools/kwboot.c
+++ b/tools/kwboot.c
@@ -9,10 +9,14 @@
  *   2008. Chapter 24.2 "BootROM Firmware".
  */
 
+#include "kwbimage.h"
+#include "mkimage.h"
+
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 #include <stdarg.h>
+#include <image.h>
 #include <libgen.h>
 #include <fcntl.h>
 #include <errno.h>
@@ -22,8 +26,6 @@
 #include <sys/mman.h>
 #include <sys/stat.h>
 
-#include "kwbimage.h"
-
 #ifdef __GNUC__
 #define PACKED __attribute((packed))
 #else
@@ -652,6 +654,14 @@ kwboot_img_patch_hdr(void *img, size_t size)
 
 	hdr->blockid = IBR_HDR_UART_ID;
 
+	/*
+	 * Subtract mkimage header size from destination address
+	 * as this header is not expected by the Marvell BootROM.
+	 * This way, the execution address is identical to the
+	 * one the image is compiled for (TEXT_BASE).
+	 */
+	hdr->destaddr = hdr->destaddr - sizeof(struct image_header);
+
 	if (image_ver == 0) {
 		struct main_hdr_v0 *hdr_v0 = img;