Merge branch 'master' of git://www.denx.de/git/u-boot-imx
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/ppa.c b/arch/arm/cpu/armv8/fsl-layerscape/ppa.c
index 35c612d..24ddb5d 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/ppa.c
+++ b/arch/arm/cpu/armv8/fsl-layerscape/ppa.c
@@ -173,8 +173,9 @@
 	debug("%s: PPA image load from NAND\n", __func__);
 
 	nand_init();
-	ret = nand_read(nand_info[0], (loff_t)CONFIG_SYS_LS_PPA_FW_ADDR,
-		       &fdt_header_len, (u_char *)&fit);
+	ret = nand_read(get_nand_dev_by_index(0),
+			(loff_t)CONFIG_SYS_LS_PPA_FW_ADDR,
+			&fdt_header_len, (u_char *)&fit);
 	if (ret == -EUCLEAN) {
 		printf("NAND read of PPA FIT header at offset 0x%x failed\n",
 		       CONFIG_SYS_LS_PPA_FW_ADDR);
@@ -196,8 +197,9 @@
 
 	fw_length = CONFIG_LS_PPA_ESBC_HDR_SIZE;
 
-	ret = nand_read(nand_info[0], (loff_t)CONFIG_SYS_LS_PPA_ESBC_ADDR,
-		       &fw_length, (u_char *)ppa_hdr_ddr);
+	ret = nand_read(get_nand_dev_by_index(0),
+			(loff_t)CONFIG_SYS_LS_PPA_ESBC_ADDR,
+			&fw_length, (u_char *)ppa_hdr_ddr);
 	if (ret == -EUCLEAN) {
 		free(ppa_hdr_ddr);
 		printf("NAND read of PPA firmware at offset 0x%x failed\n",
@@ -221,8 +223,9 @@
 		return -ENOMEM;
 	}
 
-	ret = nand_read(nand_info[0], (loff_t)CONFIG_SYS_LS_PPA_FW_ADDR,
-		       &fw_length, (u_char *)ppa_fit_addr);
+	ret = nand_read(get_nand_dev_by_index(0),
+			(loff_t)CONFIG_SYS_LS_PPA_FW_ADDR,
+			&fw_length, (u_char *)ppa_fit_addr);
 	if (ret == -EUCLEAN) {
 		free(ppa_fit_addr);
 		printf("NAND read of PPA firmware at offset 0x%x failed\n",
diff --git a/arch/arm/dts/armada-385-turris-omnia-u-boot.dtsi b/arch/arm/dts/armada-385-turris-omnia-u-boot.dtsi
new file mode 100644
index 0000000..22caf35
--- /dev/null
+++ b/arch/arm/dts/armada-385-turris-omnia-u-boot.dtsi
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2017 Marek Behun <marek.behun@nic.cz>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+/ {
+	aliases {
+		i2c0 = &i2c0;
+		i2c1 = &i2cmux;
+		spi0 = &spi0;
+	};
+};
+
+&i2c0 {
+	u-boot,dm-pre-reloc;
+
+	i2cmux: i2cmux@70 {
+		u-boot,dm-pre-reloc;
+
+		i2c@0 {
+			u-boot,dm-pre-reloc;
+		};
+
+		i2c@1 {
+			u-boot,dm-pre-reloc;
+		};
+
+		i2c@5 {
+			u-boot,dm-pre-reloc;
+
+			/* ATSHA204A at address 0x64 */
+			atsha204a@64 {
+				u-boot,dm-pre-reloc;
+				compatible = "atmel,atsha204a";
+				reg = <0x64>;
+			};
+		};
+	};
+};
+
+&spi0 {
+	u-boot,dm-pre-reloc;
+
+	spi-flash@0 {
+		compatible = "spi-flash";
+		reg = <0>;
+		spi-max-frequency = <40000000>;
+		u-boot,dm-pre-reloc;
+	};
+};
+
+&uart0 {
+	u-boot,dm-pre-reloc;
+};
diff --git a/arch/arm/dts/armada-385-turris-omnia.dts b/arch/arm/dts/armada-385-turris-omnia.dts
new file mode 100644
index 0000000..28eede1
--- /dev/null
+++ b/arch/arm/dts/armada-385-turris-omnia.dts
@@ -0,0 +1,392 @@
+/*
+ * Device Tree file for the Turris Omnia
+ *
+ * Copyright (C) 2016 Uwe Kleine-König <uwe@kleine-koenig.org>
+ * Copyright (C) 2016 Tomas Hlavacek <tmshlvkc@gmail.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is licensed under the terms of the GNU General Public
+ *     License version 2.  This program is licensed "as is" without
+ *     any warranty of any kind, whether express or implied.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Schematic available at https://www.turris.cz/doc/_media/rtrom01-schema.pdf
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include "armada-385.dtsi"
+
+/ {
+	model = "Turris Omnia";
+	compatible = "cznic,turris-omnia", "marvell,armada385", "marvell,armada380";
+
+	chosen {
+		stdout-path = &uart0;
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x40000000>; /* 1024 MB */
+	};
+
+	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 {
+
+			/* USB part of the PCIe2/USB 2.0 port */
+			usb@58000 {
+				status = "okay";
+			};
+
+			sata@a8000 {
+				status = "okay";
+			};
+
+			sdhci@d8000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&sdhci_pins>;
+				status = "okay";
+
+				bus-width = <8>;
+				no-1-8-v;
+				non-removable;
+			};
+
+			usb3@f0000 {
+				status = "okay";
+			};
+
+			usb3@f8000 {
+				status = "okay";
+			};
+		};
+
+		pcie-controller {
+			status = "okay";
+
+			pcie@1,0 {
+				/* Port 0, Lane 0 */
+				status = "okay";
+			};
+
+			pcie@2,0 {
+				/* Port 1, Lane 0 */
+				status = "okay";
+			};
+
+			pcie@3,0 {
+				/* Port 2, Lane 0 */
+				status = "okay";
+			};
+		};
+	};
+};
+
+/* Connected to 88E6176 switch, port 6 */
+&eth0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&ge0_rgmii_pins>;
+	status = "okay";
+	phy-mode = "rgmii";
+
+	fixed-link {
+		speed = <1000>;
+		full-duplex;
+	};
+};
+
+/* Connected to 88E6176 switch, port 5 */
+&eth1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&ge1_rgmii_pins>;
+	status = "okay";
+	phy-mode = "rgmii";
+
+	fixed-link {
+		speed = <1000>;
+		full-duplex;
+	};
+};
+
+/* WAN port */
+&eth2 {
+	status = "okay";
+	phy-mode = "sgmii";
+	phy = <&phy1>;
+};
+
+&i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_pins>;
+	status = "okay";
+
+	i2cmux@70 {
+		compatible = "nxp,pca9547";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x70>;
+		status = "okay";
+
+		i2c@0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+
+			/* STM32F0 command interface at address 0x2a */
+			/* leds device (in STM32F0) at address 0x2b */
+
+			eeprom@54 {
+				compatible = "at,24c64";
+				reg = <0x54>;
+
+				/* The EEPROM contains data for bootloader.
+				 * Contents:
+				 * 	struct omnia_eeprom {
+				 * 		u32 magic; (=0x0341a034 in LE)
+				 *		u32 ramsize; (in GiB)
+				 * 		char regdomain[4];
+				 * 		u32 crc32;
+				 * 	};
+				 */
+			};
+		};
+
+		i2c@1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+
+			/* routed to PCIe0/mSATA connector (CN7A) */
+		};
+
+		i2c@2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+
+			/* routed to PCIe1/USB2 connector (CN61A) */
+		};
+
+		i2c@3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+
+			/* routed to PCIe2 connector (CN62A) */
+		};
+
+		i2c@4 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <4>;
+
+			/* routed to SFP+ */
+		};
+
+		i2c@5 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <5>;
+
+			/* ATSHA204A at address 0x64 */
+		};
+
+		i2c@6 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <6>;
+
+			/* exposed on pin header */
+		};
+
+		i2c@7 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <7>;
+
+			pcawan: gpio@71 {
+				/*
+				 * GPIO expander for SFP+ signals and
+				 * and phy irq
+				 */
+				compatible = "nxp,pca9538";
+				reg = <0x71>;
+
+				pinctrl-names = "default";
+				pinctrl-0 = <&pcawan_pins>;
+
+				interrupt-parent = <&gpio1>;
+				interrupts = <14 IRQ_TYPE_LEVEL_LOW>;
+
+				gpio-controller;
+				#gpio-cells = <2>;
+			};
+		};
+	};
+};
+
+&mdio {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mdio_pins>;
+	status = "okay";
+
+	phy1: phy@1 {
+		status = "okay";
+		compatible = "ethernet-phy-id0141.0DD1", "ethernet-phy-ieee802.3-c22";
+		reg = <1>;
+
+		/* irq is connected to &pcawan pin 7 */
+	};
+
+	/* Switch MV88E6176 at address 0x10 */
+	switch@10 {
+		compatible = "marvell,mv88e6085";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		dsa,member = <0 0>;
+
+		reg = <0x10>;
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			ports@0 {
+				reg = <0>;
+				label = "lan0";
+			};
+
+			ports@1 {
+				reg = <1>;
+				label = "lan1";
+			};
+
+			ports@2 {
+				reg = <2>;
+				label = "lan2";
+			};
+
+			ports@3 {
+				reg = <3>;
+				label = "lan3";
+			};
+
+			ports@4 {
+				reg = <4>;
+				label = "lan4";
+			};
+
+			ports@5 {
+				reg = <5>;
+				label = "cpu";
+				ethernet = <&eth1>;
+				phy-mode = "rgmii-id";
+
+				fixed-link {
+					speed = <1000>;
+					full-duplex;
+				};
+			};
+
+			/* port 6 is connected to eth0 */
+		};
+	};
+};
+
+&pinctrl {
+	pcawan_pins: pcawan-pins {
+		marvell,pins = "mpp46";
+		marvell,function = "gpio";
+	};
+
+	spi0cs0_pins: spi0cs0-pins {
+		marvell,pins = "mpp25";
+		marvell,function = "spi0";
+	};
+
+	spi0cs1_pins: spi0cs1-pins {
+		marvell,pins = "mpp26";
+		marvell,function = "spi0";
+	};
+};
+
+&spi0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi0_pins &spi0cs0_pins>;
+	status = "okay";
+
+	spi-nor@0 {
+		compatible = "spansion,s25fl164k", "jedec,spi-nor";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0>;
+		spi-max-frequency = <40000000>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				reg = <0x0 0x00100000>;
+				label = "U-Boot";
+			};
+
+			partition@100000 {
+				reg = <0x00100000 0x00700000>;
+				label = "Rescue system";
+			};
+		};
+	};
+
+	/* MISO, MOSI, SCLK and CS1 are routed to pin header CN11 */
+};
+
+&uart0 {
+	/* Pin header CN10 */
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pins>;
+	status = "okay";
+};
+
+&uart1 {
+	/* Pin header CN11 */
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart1_pins>;
+	status = "okay";
+};
diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
index 3e48d58..01d700b 100644
--- a/arch/arm/mach-mvebu/Kconfig
+++ b/arch/arm/mach-mvebu/Kconfig
@@ -92,6 +92,10 @@
 	bool "Support DB-88F6820-AMC"
 	select 88F6820
 
+config TARGET_TURRIS_OMNIA
+	bool "Support Turris Omnia"
+	select 88F6820
+
 config TARGET_MVEBU_ARMADA_8K
 	bool "Support Armada 7k/8k platforms"
 	select ARMADA_8K
@@ -128,6 +132,7 @@
 	default "db-88f6720" if TARGET_DB_88F6720
 	default "db-88f6820-gp" if TARGET_DB_88F6820_GP
 	default "db-88f6820-amc" if TARGET_DB_88F6820_AMC
+	default "turris_omnia" if TARGET_TURRIS_OMNIA
 	default "mvebu_armada-8k" if TARGET_MVEBU_ARMADA_8K
 	default "db-mv784mp-gp" if TARGET_DB_MV784MP_GP
 	default "ds414" if TARGET_DS414
@@ -145,6 +150,7 @@
 	default "ds414" if TARGET_DS414
 	default "maxbcm" if TARGET_MAXBCM
 	default "theadorable" if TARGET_THEADORABLE
+	default "turris_omnia" if TARGET_TURRIS_OMNIA
 
 config SYS_VENDOR
 	default "Marvell" if TARGET_DB_MV784MP_GP
@@ -155,10 +161,26 @@
 	default "Marvell" if TARGET_MVEBU_ARMADA_8K
 	default "solidrun" if TARGET_CLEARFOG
 	default "Synology" if TARGET_DS414
+	default "CZ.NIC" if TARGET_TURRIS_OMNIA
 
 config SYS_SOC
 	default "mvebu"
 
+if TARGET_TURRIS_OMNIA
+
+choice
+	prompt "Turris Omnia boot method"
+
+config TURRIS_OMNIA_SPL_BOOT_DEVICE_SPI
+	bool "SPI NOR flash"
+
+config TURRIS_OMNIA_SPL_BOOT_DEVICE_MMC
+	bool "SDIO/MMC card"
+
+endchoice
+
+endif
+
 config MVEBU_EFUSE
 	bool "Enable eFuse support"
 	default n
diff --git a/arch/arm/mach-omap2/am33xx/board.c b/arch/arm/mach-omap2/am33xx/board.c
index db757d9..913a44a 100644
--- a/arch/arm/mach-omap2/am33xx/board.c
+++ b/arch/arm/mach-omap2/am33xx/board.c
@@ -213,11 +213,9 @@
 	.board_data	= &otg1_board_data,
 };
 #endif
-#endif
 
 int arch_misc_init(void)
 {
-#ifndef CONFIG_DM_USB
 #ifdef CONFIG_AM335X_USB0
 	musb_register(&otg0_plat, &otg0_board_data,
 		(void *)USB0_OTG_BASE);
@@ -226,7 +224,13 @@
 	musb_register(&otg1_plat, &otg1_board_data,
 		(void *)USB1_OTG_BASE);
 #endif
-#else
+	return 0;
+}
+
+#else	/* CONFIG_USB_MUSB_* && CONFIG_AM335X_USB* && !CONFIG_DM_USB */
+
+int arch_misc_init(void)
+{
 	struct udevice *dev;
 	int ret;
 
@@ -241,10 +245,12 @@
 		return ret;
 	}
 #endif
-#endif
+
 	return 0;
 }
 
+#endif /* CONFIG_USB_MUSB_* && CONFIG_AM335X_USB* && !CONFIG_DM_USB */
+
 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
 /*
  * In the case of non-SPL based booting we'll want to call these
diff --git a/arch/arm/mach-omap2/am33xx/clock_ti816x.c b/arch/arm/mach-omap2/am33xx/clock_ti816x.c
index 967623d..e9c7b2d 100644
--- a/arch/arm/mach-omap2/am33xx/clock_ti816x.c
+++ b/arch/arm/mach-omap2/am33xx/clock_ti816x.c
@@ -335,7 +335,13 @@
 	writel(PRCM_MOD_EN, &cmalwon->gpio0clkctrl);
 	while (readl(&cmalwon->gpio0clkctrl) != PRCM_MOD_EN)
 		;
-	writel((BIT(8)), &cmalwon->gpio0clkctrl);
+	writel((BIT(1) | BIT(8)), &cmalwon->gpio0clkctrl);
+
+	/* Enable gpio1 */
+	writel(PRCM_MOD_EN, &cmalwon->gpio1clkctrl);
+	while (readl(&cmalwon->gpio1clkctrl) != PRCM_MOD_EN)
+		;
+	writel((BIT(1) | BIT(8)), &cmalwon->gpio1clkctrl);
 
 	/* Enable spi */
 	writel(PRCM_MOD_EN, &cmalwon->spiclkctrl);
diff --git a/board/BuR/common/common.c b/board/BuR/common/common.c
index e8c6401..c3a56db 100644
--- a/board/BuR/common/common.c
+++ b/board/BuR/common/common.c
@@ -259,7 +259,8 @@
 	}
 #ifdef CONFIG_NAND
 	dtbsize = 0x20000;
-	rc = nand_read_skip_bad(nand_info[0], 0x40000, (size_t *)&dtbsize,
+	rc = nand_read_skip_bad(get_nand_dev_by_index(0), 0x40000,
+				(size_t *)&dtbsize,
 				NULL, 0x20000, (u_char *)dtbaddr);
 #else
 	char *dtbname = getenv("dtb");
diff --git a/board/CZ.NIC/turris_omnia/Makefile b/board/CZ.NIC/turris_omnia/Makefile
new file mode 100644
index 0000000..f2ae506
--- /dev/null
+++ b/board/CZ.NIC/turris_omnia/Makefile
@@ -0,0 +1,7 @@
+#
+# Copyright (C) 2017 Marek Behun <marek.behun@nic.cz>
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y	:= turris_omnia.o
diff --git a/board/CZ.NIC/turris_omnia/kwbimage.cfg b/board/CZ.NIC/turris_omnia/kwbimage.cfg
new file mode 100644
index 0000000..cc05792
--- /dev/null
+++ b/board/CZ.NIC/turris_omnia/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.bin 0000005b 00000068
diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c b/board/CZ.NIC/turris_omnia/turris_omnia.c
new file mode 100644
index 0000000..86926f8
--- /dev/null
+++ b/board/CZ.NIC/turris_omnia/turris_omnia.c
@@ -0,0 +1,530 @@
+/*
+ * Copyright (C) 2017 Marek Behun <marek.behun@nic.cz>
+ * Copyright (C) 2016 Tomas Hlavacek <tomas.hlavacek@nic.cz>
+ *
+ * Derived from the code for
+ *   Marvell/db-88f6820-gp by 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 <dm/uclass.h>
+#include <fdt_support.h>
+#include <time.h>
+
+#ifdef CONFIG_ATSHA204A
+# include <atsha204a-i2c.h>
+#endif
+
+#ifdef CONFIG_WDT_ORION
+# include <wdt.h>
+#endif
+
+#include "../drivers/ddr/marvell/a38x/ddr3_a38x_topology.h"
+#include <../serdes/a38x/high_speed_env_spec.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define OMNIA_I2C_EEPROM_DM_NAME	"i2c@0"
+#define OMNIA_I2C_EEPROM		0x54
+#define OMNIA_I2C_EEPROM_CONFIG_ADDR	0x0
+#define OMNIA_I2C_EEPROM_ADDRLEN	2
+#define OMNIA_I2C_EEPROM_MAGIC		0x0341a034
+
+#define OMNIA_I2C_MCU_DM_NAME		"i2c@0"
+#define OMNIA_I2C_MCU_ADDR_STATUS	0x1
+#define OMNIA_I2C_MCU_SATA		0x20
+#define OMNIA_I2C_MCU_CARDDET		0x10
+#define OMNIA_I2C_MCU			0x2a
+#define OMNIA_I2C_MCU_WDT_ADDR		0x0b
+
+#define OMNIA_ATSHA204_OTP_VERSION	0
+#define OMNIA_ATSHA204_OTP_SERIAL	1
+#define OMNIA_ATSHA204_OTP_MAC0		3
+#define OMNIA_ATSHA204_OTP_MAC1		4
+
+#define MVTWSI_ARMADA_DEBUG_REG		0x8c
+
+/*
+ * Those values and defines are taken from the Marvell U-Boot version
+ * "u-boot-2013.01-2014_T3.0"
+ */
+#define OMNIA_GPP_OUT_ENA_LOW					\
+	(~(BIT(1)  | BIT(4)  | BIT(6)  | BIT(7)  | BIT(8)  | BIT(9)  |	\
+	   BIT(10) | BIT(11) | BIT(19) | BIT(22) | BIT(23) | BIT(25) |	\
+	   BIT(26) | BIT(27) | BIT(29) | BIT(30) | BIT(31)))
+#define OMNIA_GPP_OUT_ENA_MID					\
+	(~(BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(15) |	\
+	   BIT(16) | BIT(17) | BIT(18)))
+
+#define OMNIA_GPP_OUT_VAL_LOW	0x0
+#define OMNIA_GPP_OUT_VAL_MID	0x0
+#define OMNIA_GPP_POL_LOW	0x0
+#define OMNIA_GPP_POL_MID	0x0
+
+static struct serdes_map board_serdes_map_pex[] = {
+	{PEX0, SERDES_SPEED_5_GBPS, PEX_ROOT_COMPLEX_X1, 0, 0},
+	{USB3_HOST0, SERDES_SPEED_5_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}
+};
+
+static struct serdes_map board_serdes_map_sata[] = {
+	{SATA0, SERDES_SPEED_6_GBPS, SERDES_DEFAULT_MODE, 0, 0},
+	{USB3_HOST0, SERDES_SPEED_5_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}
+};
+
+static bool omnia_detect_sata(void)
+{
+	struct udevice *bus, *dev;
+	int ret;
+	u16 mode;
+
+	puts("SERDES0 card detect: ");
+
+	if (uclass_get_device_by_name(UCLASS_I2C, OMNIA_I2C_MCU_DM_NAME, &bus)) {
+		puts("Cannot find MCU bus!\n");
+		return false;
+	}
+
+	ret = i2c_get_chip(bus, OMNIA_I2C_MCU, 1, &dev);
+	if (ret) {
+		puts("Cannot get MCU chip!\n");
+		return false;
+	}
+
+	ret = dm_i2c_read(dev, OMNIA_I2C_MCU_ADDR_STATUS, (uchar *) &mode, 2);
+	if (ret) {
+		puts("I2C read failed! Default PEX\n");
+		return false;
+	}
+
+	if (!(mode & OMNIA_I2C_MCU_CARDDET)) {
+		puts("NONE\n");
+		return false;
+	}
+
+	if (mode & OMNIA_I2C_MCU_SATA) {
+		puts("SATA\n");
+		return true;
+	} else {
+		puts("PEX\n");
+		return false;
+	}
+}
+
+int hws_board_topology_load(struct serdes_map **serdes_map_array, u8 *count)
+{
+	if (omnia_detect_sata()) {
+		*serdes_map_array = board_serdes_map_sata;
+		*count = ARRAY_SIZE(board_serdes_map_sata);
+	} else {
+		*serdes_map_array = board_serdes_map_pex;
+		*count = ARRAY_SIZE(board_serdes_map_pex);
+	}
+
+	return 0;
+}
+
+struct omnia_eeprom {
+	u32 magic;
+	u32 ramsize;
+	char region[4];
+	u32 crc;
+};
+
+static bool omnia_read_eeprom(struct omnia_eeprom *oep)
+{
+	struct udevice *bus, *dev;
+	int ret, crc, retry = 3;
+
+	if (uclass_get_device_by_name(UCLASS_I2C, OMNIA_I2C_EEPROM_DM_NAME, &bus)) {
+		puts("Cannot find EEPROM bus\n");
+		return false;
+	}
+
+	ret = i2c_get_chip(bus, OMNIA_I2C_EEPROM, OMNIA_I2C_EEPROM_ADDRLEN, &dev);
+	if (ret) {
+		puts("Cannot get EEPROM chip\n");
+		return false;
+	}
+
+	for (; retry > 0; --retry) {
+		ret = dm_i2c_read(dev, OMNIA_I2C_EEPROM_CONFIG_ADDR, (uchar *) oep, sizeof(struct omnia_eeprom));
+		if (ret)
+			continue;
+
+		if (oep->magic != OMNIA_I2C_EEPROM_MAGIC) {
+			puts("I2C EEPROM missing magic number!\n");
+			continue;
+		}
+
+		crc = crc32(0, (unsigned char *) oep,
+			    sizeof(struct omnia_eeprom) - 4);
+		if (crc == oep->crc) {
+			break;
+		} else {
+			printf("CRC of EEPROM memory config failed! "
+			       "calc=0x%04x saved=0x%04x\n", crc, oep->crc);
+		}
+	}
+
+	if (!retry) {
+		puts("I2C EEPROM read failed!\n");
+		return false;
+	}
+
+	return true;
+}
+
+/*
+ * 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_1g = {
+	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_NORMAL,		/* temperature */
+	    HWS_TIM_2T} },		/* timing (force 2t) */
+	5,				/* Num Of Bus Per Interface*/
+	BUS_MASK_32BIT			/* Busses mask */
+};
+
+static struct hws_topology_map board_topology_map_2g = {
+	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_8G,			/* mem_size */
+	    DDR_FREQ_800,		/* frequency */
+	    0, 0,			/* cas_l cas_wl */
+	    HWS_TEMP_NORMAL,		/* temperature */
+	    HWS_TIM_2T} },		/* timing (force 2t) */
+	5,				/* Num Of Bus Per Interface*/
+	BUS_MASK_32BIT			/* Busses mask */
+};
+
+struct hws_topology_map *ddr3_get_topology_map(void)
+{
+	static int mem = 0;
+	struct omnia_eeprom oep;
+
+	/* Get the board config from EEPROM */
+	if (mem == 0) {
+		if(!omnia_read_eeprom(&oep))
+			goto out;
+
+		printf("Memory config in EEPROM: 0x%02x\n", oep.ramsize);
+
+		if (oep.ramsize == 0x2)
+			mem = 2;
+		else
+			mem = 1;
+	}
+
+out:
+	/* Hardcoded fallback */
+	if (mem == 0) {
+		puts("WARNING: Memory config from EEPROM read failed.\n");
+		puts("Falling back to default 1GiB map.\n");
+		mem = 1;
+	}
+
+	/* Return the board topology as defined in the board code */
+	if (mem == 1)
+		return &board_topology_map_1g;
+	if (mem == 2)
+		return &board_topology_map_2g;
+
+	return &board_topology_map_1g;
+}
+
+#ifndef CONFIG_SPL_BUILD
+static int set_regdomain(void)
+{
+	struct omnia_eeprom oep;
+	char rd[3] = {' ', ' ', 0};
+
+	if (omnia_read_eeprom(&oep))
+		memcpy(rd, &oep.region, 2);
+	else
+		puts("EEPROM regdomain read failed.\n");
+
+	printf("Regdomain set to %s\n", rd);
+	return setenv("regdomain", rd);
+}
+#endif
+
+int board_early_init_f(void)
+{
+	u32 i2c_debug_reg;
+
+	/* Configure MPP */
+	writel(0x11111111, MVEBU_MPP_BASE + 0x00);
+	writel(0x11111111, MVEBU_MPP_BASE + 0x04);
+	writel(0x11244011, MVEBU_MPP_BASE + 0x08);
+	writel(0x22222111, MVEBU_MPP_BASE + 0x0c);
+	writel(0x22200002, MVEBU_MPP_BASE + 0x10);
+	writel(0x30042022, MVEBU_MPP_BASE + 0x14);
+	writel(0x55550555, MVEBU_MPP_BASE + 0x18);
+	writel(0x00005550, MVEBU_MPP_BASE + 0x1c);
+
+	/* Set GPP Out value */
+	writel(OMNIA_GPP_OUT_VAL_LOW, MVEBU_GPIO0_BASE + 0x00);
+	writel(OMNIA_GPP_OUT_VAL_MID, MVEBU_GPIO1_BASE + 0x00);
+
+	/* Set GPP Polarity */
+	writel(OMNIA_GPP_POL_LOW, MVEBU_GPIO0_BASE + 0x0c);
+	writel(OMNIA_GPP_POL_MID, MVEBU_GPIO1_BASE + 0x0c);
+
+	/* Set GPP Out Enable */
+	writel(OMNIA_GPP_OUT_ENA_LOW, MVEBU_GPIO0_BASE + 0x04);
+	writel(OMNIA_GPP_OUT_ENA_MID, MVEBU_GPIO1_BASE + 0x04);
+
+	/* Disable I2C debug mode blocking 0x64 I2C address */
+	i2c_debug_reg = readl(MVEBU_TWSI_BASE + MVTWSI_ARMADA_DEBUG_REG);
+	i2c_debug_reg &= ~(1<<18);
+	writel(i2c_debug_reg, MVEBU_TWSI_BASE + MVTWSI_ARMADA_DEBUG_REG);
+
+	return 0;
+}
+
+#ifndef CONFIG_SPL_BUILD
+static bool disable_mcu_watchdog(void)
+{
+	struct udevice *bus, *dev;
+	int ret, retry = 3;
+	uchar buf[1] = {0x0};
+
+	if (uclass_get_device_by_name(UCLASS_I2C, OMNIA_I2C_MCU_DM_NAME, &bus)) {
+		puts("Cannot find MCU bus! Can not disable MCU WDT.\n");
+		return false;
+	}
+
+	ret = i2c_get_chip(bus, OMNIA_I2C_MCU, 1, &dev);
+	if (ret) {
+		puts("Cannot get MCU chip! Can not disable MCU WDT.\n");
+		return false;
+	}
+
+	for (; retry > 0; --retry)
+		if (!dm_i2c_write(dev, OMNIA_I2C_MCU_WDT_ADDR, (uchar *) buf, 1))
+			break;
+
+	if (retry <= 0) {
+		puts("I2C MCU watchdog failed to disable!\n");
+		return false;
+	}
+
+	return true;
+}
+#endif
+
+#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_WDT_ORION)
+static struct udevice *watchdog_dev = NULL;
+#endif
+
+int board_init(void)
+{
+	/* adress of boot parameters */
+	gd->bd->bi_boot_params = mvebu_sdram_bar(0) + 0x100;
+
+#ifndef CONFIG_SPL_BUILD
+# ifdef CONFIG_WDT_ORION
+	if (uclass_get_device(UCLASS_WDT, 0, &watchdog_dev)) {
+		puts("Cannot find Armada 385 watchdog!\n");
+	} else {
+		puts("Enabling Armada 385 watchdog.\n");
+		wdt_start(watchdog_dev, (u32) 25000000 * 120, 0);
+	}
+# endif
+
+	if (disable_mcu_watchdog())
+		puts("Disabled MCU startup watchdog.\n");
+
+	set_regdomain();
+#endif
+
+	return 0;
+}
+
+#ifdef CONFIG_WATCHDOG
+/* Called by macro WATCHDOG_RESET */
+void watchdog_reset(void)
+{
+# if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_WDT_ORION)
+	static ulong next_reset = 0;
+	ulong now;
+
+	if (!watchdog_dev)
+		return;
+
+	now = timer_get_us();
+
+	/* Do not reset the watchdog too often */
+	if (now > next_reset) {
+		wdt_reset(watchdog_dev);
+		next_reset = now + 1000;
+	}
+# endif
+}
+#endif
+
+int board_late_init(void)
+{
+#ifndef CONFIG_SPL_BUILD
+	set_regdomain();
+#endif
+
+	return 0;
+}
+
+#ifdef CONFIG_ATSHA204A
+static struct udevice *get_atsha204a_dev(void)
+{
+	static struct udevice *dev = NULL;
+
+	if (dev != NULL)
+		return dev;
+
+	if (uclass_get_device_by_name(UCLASS_MISC, "atsha204a@64", &dev)) {
+		puts("Cannot find ATSHA204A on I2C bus!\n");
+		dev = NULL;
+	}
+
+	return dev;
+}
+#endif
+
+int checkboard(void)
+{
+	u32 version_num, serial_num;
+	int err = 1;
+
+#ifdef CONFIG_ATSHA204A
+	struct udevice *dev = get_atsha204a_dev();
+
+	if (dev) {
+		err = atsha204a_wakeup(dev);
+		if (err)
+			goto out;
+
+		err = atsha204a_read(dev, ATSHA204A_ZONE_OTP, false,
+				     OMNIA_ATSHA204_OTP_VERSION,
+				     (u8 *) &version_num);
+		if (err)
+			goto out;
+
+		err = atsha204a_read(dev, ATSHA204A_ZONE_OTP, false,
+				     OMNIA_ATSHA204_OTP_SERIAL,
+				     (u8 *) &serial_num);
+		if (err)
+			goto out;
+
+		atsha204a_sleep(dev);
+	}
+
+out:
+#endif
+
+	if (err)
+		printf("Board: Turris Omnia (ver N/A). SN: N/A\n");
+	else
+		printf("Board: Turris Omnia SNL %08X%08X\n",
+		       be32_to_cpu(version_num), be32_to_cpu(serial_num));
+
+	return 0;
+}
+
+static void increment_mac(u8 *mac)
+{
+	int i;
+
+	for (i = 5; i >= 3; i--) {
+		mac[i] += 1;
+		if (mac[i])
+			break;
+	}
+}
+
+int misc_init_r(void)
+{
+#ifdef CONFIG_ATSHA204A
+	int err;
+	struct udevice *dev = get_atsha204a_dev();
+	u8 mac0[4], mac1[4], mac[6];
+
+	if (!dev)
+		goto out;
+
+	err = atsha204a_wakeup(dev);
+	if (err)
+		goto out;
+
+	err = atsha204a_read(dev, ATSHA204A_ZONE_OTP, false,
+			     OMNIA_ATSHA204_OTP_MAC0, mac0);
+	if (err)
+		goto out;
+
+	err = atsha204a_read(dev, ATSHA204A_ZONE_OTP, false,
+			     OMNIA_ATSHA204_OTP_MAC1, mac1);
+	if (err)
+		goto out;
+
+	atsha204a_sleep(dev);
+
+	mac[0] = mac0[1];
+	mac[1] = mac0[2];
+	mac[2] = mac0[3];
+	mac[3] = mac1[1];
+	mac[4] = mac1[2];
+	mac[5] = mac1[3];
+
+	if (is_valid_ethaddr(mac))
+		eth_setenv_enetaddr("ethaddr", mac);
+
+	increment_mac(mac);
+
+	if (is_valid_ethaddr(mac))
+		eth_setenv_enetaddr("eth1addr", mac);
+
+	increment_mac(mac);
+
+	if (is_valid_ethaddr(mac))
+		eth_setenv_enetaddr("eth2addr", mac);
+
+out:
+#endif
+
+	return 0;
+}
+
diff --git a/board/Marvell/db-88f6820-amc/db-88f6820-amc.c b/board/Marvell/db-88f6820-amc/db-88f6820-amc.c
index cade99c..40fa599 100644
--- a/board/Marvell/db-88f6820-amc/db-88f6820-amc.c
+++ b/board/Marvell/db-88f6820-amc/db-88f6820-amc.c
@@ -69,7 +69,8 @@
 	    MEM_4G,			/* mem_size */
 	    DDR_FREQ_800,		/* frequency */
 	    0, 0,			/* cas_l cas_wl */
-	    HWS_TEMP_LOW} },		/* temperature */
+	    HWS_TEMP_LOW,		/* temperature */
+	    HWS_TIM_DEFAULT} },		/* timing */
 	5,				/* Num Of Bus Per Interface*/
 	BUS_MASK_32BIT			/* Busses mask */
 };
diff --git a/board/Marvell/db-88f6820-gp/db-88f6820-gp.c b/board/Marvell/db-88f6820-gp/db-88f6820-gp.c
index e700781..a1974cb 100644
--- a/board/Marvell/db-88f6820-gp/db-88f6820-gp.c
+++ b/board/Marvell/db-88f6820-gp/db-88f6820-gp.c
@@ -90,7 +90,8 @@
 	    MEM_4G,			/* mem_size */
 	    DDR_FREQ_800,		/* frequency */
 	    0, 0,			/* cas_l cas_wl */
-	    HWS_TEMP_LOW} },		/* temperature */
+	    HWS_TEMP_LOW,		/* temperature */
+	    HWS_TIM_DEFAULT} },		/* timing */
 	5,				/* Num Of Bus Per Interface*/
 	BUS_MASK_32BIT			/* Busses mask */
 };
diff --git a/board/atmel/at91sam9261ek/at91sam9261ek.c b/board/atmel/at91sam9261ek/at91sam9261ek.c
index b4acb74..1ba6063 100644
--- a/board/atmel/at91sam9261ek/at91sam9261ek.c
+++ b/board/atmel/at91sam9261ek/at91sam9261ek.c
@@ -213,7 +213,7 @@
 		dram_size += gd->bd->bi_dram[i].size;
 	nand_size = 0;
 	for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
-		nand_size += nand_info[i]->size;
+		nand_size += get_nand_dev_by_index(i)->size;
 	lcd_printf ("  %ld MB SDRAM, %ld MB NAND\n",
 		dram_size >> 20,
 		nand_size >> 20 );
diff --git a/board/atmel/at91sam9263ek/at91sam9263ek.c b/board/atmel/at91sam9263ek/at91sam9263ek.c
index b37e9d3..9fa6893 100644
--- a/board/atmel/at91sam9263ek/at91sam9263ek.c
+++ b/board/atmel/at91sam9263ek/at91sam9263ek.c
@@ -160,7 +160,7 @@
 		dram_size += gd->bd->bi_dram[i].size;
 	nand_size = 0;
 	for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
-		nand_size += nand_info[i]->size;
+		nand_size += get_nand_dev_by_index(i)->size;
 #ifdef CONFIG_MTD_NOR_FLASH
 	flash_size = 0;
 	for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++)
diff --git a/board/atmel/at91sam9m10g45ek/at91sam9m10g45ek.c b/board/atmel/at91sam9m10g45ek/at91sam9m10g45ek.c
index 8e37759..903732b 100644
--- a/board/atmel/at91sam9m10g45ek/at91sam9m10g45ek.c
+++ b/board/atmel/at91sam9m10g45ek/at91sam9m10g45ek.c
@@ -236,7 +236,7 @@
 		dram_size += gd->bd->bi_dram[i].size;
 	nand_size = 0;
 	for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
-		nand_size += nand_info[i]->size;
+		nand_size += get_nand_dev_by_index(i)->size;
 	lcd_printf ("  %ld MB SDRAM, %ld MB NAND\n",
 		dram_size >> 20,
 		nand_size >> 20 );
diff --git a/board/atmel/at91sam9n12ek/at91sam9n12ek.c b/board/atmel/at91sam9n12ek/at91sam9n12ek.c
index 1105428..fec9316 100644
--- a/board/atmel/at91sam9n12ek/at91sam9n12ek.c
+++ b/board/atmel/at91sam9n12ek/at91sam9n12ek.c
@@ -124,7 +124,7 @@
 		dram_size += gd->bd->bi_dram[i].size;
 	nand_size = 0;
 	for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
-		nand_size += nand_info[i]->size;
+		nand_size += get_nand_dev_by_index(i)->size;
 	lcd_printf("  %ld MB SDRAM, %ld MB NAND\n",
 		dram_size >> 20,
 		nand_size >> 20);
diff --git a/board/atmel/at91sam9rlek/at91sam9rlek.c b/board/atmel/at91sam9rlek/at91sam9rlek.c
index 7966269..672b376 100644
--- a/board/atmel/at91sam9rlek/at91sam9rlek.c
+++ b/board/atmel/at91sam9rlek/at91sam9rlek.c
@@ -149,7 +149,7 @@
 		dram_size += gd->bd->bi_dram[i].size;
 	nand_size = 0;
 	for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
-		nand_size += nand_info[i]->size;
+		nand_size += get_nand_dev_by_index(i)->size;
 	lcd_printf ("  %ld MB SDRAM, %ld MB NAND\n",
 		dram_size >> 20,
 		nand_size >> 20 );
diff --git a/board/atmel/at91sam9x5ek/at91sam9x5ek.c b/board/atmel/at91sam9x5ek/at91sam9x5ek.c
index 1e4a4a2..2452e63 100644
--- a/board/atmel/at91sam9x5ek/at91sam9x5ek.c
+++ b/board/atmel/at91sam9x5ek/at91sam9x5ek.c
@@ -175,7 +175,7 @@
 			dram_size += gd->bd->bi_dram[i].size;
 		nand_size = 0;
 		for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
-			nand_size += nand_info[i]->size;
+			nand_size += get_nand_dev_by_index(i)->size;
 		lcd_printf("  %ld MB SDRAM, %ld MB NAND\n",
 			dram_size >> 20,
 			nand_size >> 20);
diff --git a/board/atmel/sama5d3xek/sama5d3xek.c b/board/atmel/sama5d3xek/sama5d3xek.c
index cae6e24..c1f2769 100644
--- a/board/atmel/sama5d3xek/sama5d3xek.c
+++ b/board/atmel/sama5d3xek/sama5d3xek.c
@@ -198,7 +198,7 @@
 	nand_size = 0;
 #ifdef CONFIG_NAND_ATMEL
 	for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
-		nand_size += nand_info[i]->size;
+		nand_size += get_nand_dev_by_index(i)->size;
 #endif
 	lcd_printf("%ld MB SDRAM, %lld MB NAND\n",
 		   dram_size >> 20, nand_size >> 20);
diff --git a/board/atmel/sama5d4_xplained/sama5d4_xplained.c b/board/atmel/sama5d4_xplained/sama5d4_xplained.c
index 94ecab2..854afcb 100644
--- a/board/atmel/sama5d4_xplained/sama5d4_xplained.c
+++ b/board/atmel/sama5d4_xplained/sama5d4_xplained.c
@@ -157,7 +157,7 @@
 	nand_size = 0;
 #ifdef CONFIG_NAND_ATMEL
 	for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
-		nand_size += nand_info[i]->size;
+		nand_size += get_nand_dev_by_index(i)->size;
 #endif
 	lcd_printf("%ld MB SDRAM, %ld MB NAND\n",
 		   dram_size >> 20, nand_size >> 20);
diff --git a/board/atmel/sama5d4ek/sama5d4ek.c b/board/atmel/sama5d4ek/sama5d4ek.c
index b2e7979..ba79746 100644
--- a/board/atmel/sama5d4ek/sama5d4ek.c
+++ b/board/atmel/sama5d4ek/sama5d4ek.c
@@ -153,7 +153,7 @@
 	nand_size = 0;
 #ifdef CONFIG_NAND_ATMEL
 	for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
-		nand_size += nand_info[i]->size;
+		nand_size += get_nand_dev_by_index(i)->size;
 #endif
 	lcd_printf("%ld MB SDRAM, %ld MB NAND\n",
 		   dram_size >> 20, nand_size >> 20);
diff --git a/board/gdsys/a38x/controlcenterdc.c b/board/gdsys/a38x/controlcenterdc.c
index f0efb53..32168d3 100644
--- a/board/gdsys/a38x/controlcenterdc.c
+++ b/board/gdsys/a38x/controlcenterdc.c
@@ -53,7 +53,8 @@
 	    MEM_4G,			/* mem_size */
 	    DDR_FREQ_533,		/* frequency */
 	    0, 0,			/* cas_l cas_wl */
-	    HWS_TEMP_LOW} },		/* temperature */
+	    HWS_TEMP_LOW,		/* temperature */
+	    HWS_TIM_DEFAULT} },		/* timing */
 	5,				/* Num Of Bus Per Interface*/
 	BUS_MASK_32BIT			/* Busses mask */
 };
diff --git a/board/ronetix/pm9261/pm9261.c b/board/ronetix/pm9261/pm9261.c
index f60ddda..160f8f8 100644
--- a/board/ronetix/pm9261/pm9261.c
+++ b/board/ronetix/pm9261/pm9261.c
@@ -195,7 +195,7 @@
 
 	nand_size = 0;
 	for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
-		nand_size += nand_info[i]->size;
+		nand_size += get_nand_dev_by_index(i)->size;
 
 	flash_size = 0;
 	for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++)
diff --git a/board/ronetix/pm9263/pm9263.c b/board/ronetix/pm9263/pm9263.c
index 1469136..0c23bb6 100644
--- a/board/ronetix/pm9263/pm9263.c
+++ b/board/ronetix/pm9263/pm9263.c
@@ -294,7 +294,7 @@
 
 	nand_size = 0;
 	for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
-		nand_size += nand_info[i]->size;
+		nand_size += get_nand_dev_by_index(i)->size;
 
 	flash_size = 0;
 	for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++)
diff --git a/board/solidrun/clearfog/clearfog.c b/board/solidrun/clearfog/clearfog.c
index 3a8257c..8906636 100644
--- a/board/solidrun/clearfog/clearfog.c
+++ b/board/solidrun/clearfog/clearfog.c
@@ -83,7 +83,8 @@
 	    MEM_4G,			/* mem_size */
 	    DDR_FREQ_800,		/* frequency */
 	    0, 0,			/* cas_l cas_wl */
-	    HWS_TEMP_LOW} },		/* temperature */
+	    HWS_TEMP_LOW,		/* temperature */
+	    HWS_TIM_DEFAULT} },		/* timing */
 	5,				/* Num Of Bus Per Interface*/
 	BUS_MASK_32BIT			/* Busses mask */
 };
diff --git a/board/solidrun/clearfog/kwbimage.cfg b/board/solidrun/clearfog/kwbimage.cfg
index c650c2c..f41d25a 100644
--- a/board/solidrun/clearfog/kwbimage.cfg
+++ b/board/solidrun/clearfog/kwbimage.cfg
@@ -2,7 +2,7 @@
 # Copyright (C) 2015 Stefan Roese <sr@denx.de>
 #
 
-# Armada XP uses version 1 image format
+# Armada 38x use version 1 image format
 VERSION		1
 
 # Boot Media configurations
diff --git a/board/toradex/colibri_t20/colibri_t20.c b/board/toradex/colibri_t20/colibri_t20.c
index 7d574fb..71b8fd3 100644
--- a/board/toradex/colibri_t20/colibri_t20.c
+++ b/board/toradex/colibri_t20/colibri_t20.c
@@ -69,7 +69,7 @@
 {
 	printf("Model: Toradex Colibri T20 %dMB V%s\n",
 	       (gd->ram_size == 0x10000000) ? 256 : 512,
-	       (nand_info[0]->erasesize >> 10 == 512) ?
+	       (get_nand_dev_by_index(0)->erasesize >> 10 == 512) ?
 	       ((gd->ram_size == 0x10000000) ? "1.1B" : "1.1C") : "1.2A");
 
 	return 0;
diff --git a/board/toradex/common/tdx-cfg-block.c b/board/toradex/common/tdx-cfg-block.c
index 68ec436..1bf8ca8 100644
--- a/board/toradex/common/tdx-cfg-block.c
+++ b/board/toradex/common/tdx-cfg-block.c
@@ -154,8 +154,10 @@
 	size_t size = TDX_CFG_BLOCK_MAX_SIZE;
 
 	/* Read production parameter config block from NAND page */
-	return nand_read_skip_bad(nand_info[0], CONFIG_TDX_CFG_BLOCK_OFFSET,
-			 &size, NULL, TDX_CFG_BLOCK_MAX_SIZE, config_block);
+	return nand_read_skip_bad(get_nand_dev_by_index(0),
+				  CONFIG_TDX_CFG_BLOCK_OFFSET,
+				  &size, NULL, TDX_CFG_BLOCK_MAX_SIZE,
+				  config_block);
 }
 
 static int write_tdx_cfg_block_to_nand(unsigned char *config_block)
@@ -163,7 +165,8 @@
 	size_t size = TDX_CFG_BLOCK_MAX_SIZE;
 
 	/* Write production parameter config block to NAND page */
-	return nand_write_skip_bad(nand_info[0], CONFIG_TDX_CFG_BLOCK_OFFSET,
+	return nand_write_skip_bad(get_nand_dev_by_index(0),
+				   CONFIG_TDX_CFG_BLOCK_OFFSET,
 				   &size, NULL, TDX_CFG_BLOCK_MAX_SIZE,
 				   config_block, WITH_WR_VERIFY);
 }
@@ -426,7 +429,8 @@
 		 * empty (config block invalid...)
 		 */
 		printf("NAND erase block %d need to be erased before creating a Toradex config block\n",
-		       CONFIG_TDX_CFG_BLOCK_OFFSET / nand_info[0]->erasesize);
+		       CONFIG_TDX_CFG_BLOCK_OFFSET /
+		       get_nand_dev_by_index(0)->erasesize);
 		goto out;
 #elif defined(CONFIG_TDX_CFG_BLOCK_IS_IN_NOR)
 		/*
diff --git a/cmd/bootm.c b/cmd/bootm.c
index 953a57d..daf15d9 100644
--- a/cmd/bootm.c
+++ b/cmd/bootm.c
@@ -465,7 +465,7 @@
 	printf("\n");
 
 	for (nand_dev = 0; nand_dev < CONFIG_SYS_MAX_NAND_DEVICE; nand_dev++) {
-		mtd = nand_info[nand_dev];
+		mtd = get_nand_dev_by_index(nand_dev);
 		if (!mtd->name || !mtd->size)
 			continue;
 
diff --git a/cmd/jffs2.c b/cmd/jffs2.c
index 9be198e..dc94705 100644
--- a/cmd/jffs2.c
+++ b/cmd/jffs2.c
@@ -166,8 +166,9 @@
 #endif
 	} else if (type == MTD_DEV_TYPE_NAND) {
 #if defined(CONFIG_JFFS2_NAND) && defined(CONFIG_CMD_NAND)
-		if (num < CONFIG_SYS_MAX_NAND_DEVICE) {
-			*size = nand_info[num]->size;
+		struct mtd_info *mtd = get_nand_dev_by_index(num);
+		if (mtd) {
+			*size = mtd->size;
 			return 0;
 		}
 
@@ -244,7 +245,7 @@
 #if defined(CONFIG_JFFS2_NAND) && defined(CONFIG_CMD_NAND)
 	struct mtd_info *mtd;
 
-	mtd = nand_info[id->num];
+	mtd = get_nand_dev_by_index(id->num);
 
 	return mtd->erasesize;
 #else
diff --git a/cmd/mvebu/bubt.c b/cmd/mvebu/bubt.c
index 1e1f0af..ea46e7b 100644
--- a/cmd/mvebu/bubt.c
+++ b/cmd/mvebu/bubt.c
@@ -311,23 +311,21 @@
 {
 	int ret;
 	uint32_t block_size;
-	struct mtd_info *nand;
-	int dev = nand_curr_device;
+	struct mtd_info *mtd;
 
-	if ((dev < 0) || (dev >= CONFIG_SYS_MAX_NAND_DEVICE) ||
-	    (!nand_info[dev]->name)) {
+	mtd = get_nand_dev_by_index(nand_curr_device);
+	if (!mtd) {
 		puts("\nno devices available\n");
 		return -ENOMEDIUM;
 	}
-	nand = nand_info[dev];
-	block_size = nand->erasesize;
+	block_size = mtd->erasesize;
 
 	/* Align U-Boot size to currently used blocksize */
 	image_size = ((image_size + (block_size - 1)) & (~(block_size - 1)));
 
 	/* Erase the U-BOOT image space */
 	printf("Erasing 0x%x - 0x%x:...", 0, (int)image_size);
-	ret = nand_erase(nand, 0, image_size);
+	ret = nand_erase(mtd, 0, image_size);
 	if (ret) {
 		printf("Error!\n");
 		goto error;
@@ -337,7 +335,7 @@
 	/* Write the image to flash */
 	printf("Writing %d bytes from 0x%lx to offset 0 ... ",
 	       (int)image_size, get_load_addr());
-	ret = nand_write(nand, 0, &image_size, (void *)get_load_addr());
+	ret = nand_write(mtd, 0, &image_size, (void *)get_load_addr());
 	if (ret)
 		printf("Error!\n");
 	else
diff --git a/cmd/nand.c b/cmd/nand.c
index 72ca88a..a2152ec 100644
--- a/cmd/nand.c
+++ b/cmd/nand.c
@@ -115,20 +115,20 @@
 
 static int set_dev(int dev)
 {
-	if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE || !nand_info[dev]) {
-		puts("No such device\n");
-		return -1;
-	}
+	struct mtd_info *mtd = get_nand_dev_by_index(dev);
+
+	if (!mtd)
+		return -ENODEV;
 
 	if (nand_curr_device == dev)
 		return 0;
 
-	printf("Device %d: %s", dev, nand_info[dev]->name);
+	printf("Device %d: %s", dev, mtd->name);
 	puts("... is now current device\n");
 	nand_curr_device = dev;
 
 #ifdef CONFIG_SYS_NAND_SELECT_DEVICE
-	board_nand_select_device(nand_info[dev]->priv, dev);
+	board_nand_select_device(mtd_to_nand(mtd), dev);
 #endif
 
 	return 0;
@@ -188,7 +188,7 @@
 {
 	int ret;
 	uint32_t oob_buf[ENV_OFFSET_SIZE/sizeof(uint32_t)];
-	struct mtd_info *mtd = nand_info[0];
+	struct mtd_info *mtd = get_nand_dev_by_index(0);
 	char *cmd = argv[1];
 
 	if (CONFIG_SYS_MAX_NAND_DEVICE == 0 || !mtd) {
@@ -213,9 +213,10 @@
 		if (argc < 3)
 			goto usage;
 
+		mtd = get_nand_dev_by_index(idx);
 		/* We don't care about size, or maxsize. */
 		if (mtd_arg_off(argv[2], &idx, &addr, &maxsize, &maxsize,
-				MTD_DEV_TYPE_NAND, nand_info[idx]->size)) {
+				MTD_DEV_TYPE_NAND, mtd->size)) {
 			puts("Offset or partition name expected\n");
 			return 1;
 		}
@@ -283,9 +284,14 @@
 
 static void nand_print_and_set_info(int idx)
 {
-	struct mtd_info *mtd = nand_info[idx];
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct mtd_info *mtd;
+	struct nand_chip *chip;
 
+	mtd = get_nand_dev_by_index(idx);
+	if (!mtd)
+		return;
+
+	chip = mtd_to_nand(mtd);
 	printf("Device %d: ", idx);
 	if (chip->numchips > 1)
 		printf("%dx ", chip->numchips);
@@ -348,7 +354,7 @@
 	/* We grab the nand info object here fresh because this is usually
 	 * called after arg_off_size() which can change the value of dev.
 	 */
-	struct mtd_info *mtd = nand_info[dev];
+	struct mtd_info *mtd = get_nand_dev_by_index(dev);
 	loff_t maxoffset = offset + *size;
 	int badblocks = 0;
 
@@ -397,10 +403,8 @@
 	if (strcmp(cmd, "info") == 0) {
 
 		putc('\n');
-		for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) {
-			if (nand_info[i])
-				nand_print_and_set_info(i);
-		}
+		for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
+			nand_print_and_set_info(i);
 		return 0;
 	}
 
@@ -432,12 +436,11 @@
 	 * one before these commands can run, even if a partition specifier
 	 * for another device is to be used.
 	 */
-	if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE ||
-	    !nand_info[dev]) {
+	mtd = get_nand_dev_by_index(dev);
+	if (!mtd) {
 		puts("\nno devices available\n");
 		return 1;
 	}
-	mtd = nand_info[dev];
 
 	if (strcmp(cmd, "bad") == 0) {
 		printf("\nDevice %d bad blocks:\n", dev);
@@ -496,13 +499,13 @@
 		/* skip first two or three arguments, look for offset and size */
 		if (mtd_arg_off_size(argc - o, argv + o, &dev, &off, &size,
 				     &maxsize, MTD_DEV_TYPE_NAND,
-				     nand_info[dev]->size) != 0)
+				     mtd->size) != 0)
 			return 1;
 
 		if (set_dev(dev))
 			return 1;
 
-		mtd = nand_info[dev];
+		mtd = get_nand_dev_by_index(dev);
 
 		memset(&opts, 0, sizeof(opts));
 		opts.offset = off;
@@ -565,13 +568,13 @@
 
 			if (mtd_arg_off(argv[3], &dev, &off, &size, &maxsize,
 					MTD_DEV_TYPE_NAND,
-					nand_info[dev]->size))
+					mtd->size))
 				return 1;
 
 			if (set_dev(dev))
 				return 1;
 
-			mtd = nand_info[dev];
+			mtd = get_nand_dev_by_index(dev);
 
 			if (argc > 4 && !str2long(argv[4], &pagecount)) {
 				printf("'%s' is not a number\n", argv[4]);
@@ -588,7 +591,7 @@
 			if (mtd_arg_off_size(argc - 3, argv + 3, &dev, &off,
 					     &size, &maxsize,
 					     MTD_DEV_TYPE_NAND,
-					     nand_info[dev]->size) != 0)
+					     mtd->size) != 0)
 				return 1;
 
 			if (set_dev(dev))
@@ -600,7 +603,7 @@
 			rwsize = size;
 		}
 
-		mtd = nand_info[dev];
+		mtd = get_nand_dev_by_index(dev);
 
 		if (!s || !strcmp(s, ".jffs2") ||
 		    !strcmp(s, ".e") || !strcmp(s, ".i")) {
@@ -760,13 +763,15 @@
 
 		if (mtd_arg_off_size(argc - 2, argv + 2, &dev, &off, &size,
 				     &maxsize, MTD_DEV_TYPE_NAND,
-				     nand_info[dev]->size) < 0)
+				     mtd->size) < 0)
 			return 1;
 
 		if (set_dev(dev))
 			return 1;
 
-		if (!nand_unlock(nand_info[dev], off, size, allexcept)) {
+		mtd = get_nand_dev_by_index(dev);
+
+		if (!nand_unlock(mtd, off, size, allexcept)) {
 			puts("NAND flash successfully unlocked\n");
 		} else {
 			puts("Error unlocking NAND flash, "
@@ -929,6 +934,7 @@
 	char *boot_device = NULL;
 	int idx;
 	ulong addr, offset = 0;
+	struct mtd_info *mtd;
 #if defined(CONFIG_CMD_MTDPARTS)
 	struct mtd_device *dev;
 	struct part_info *part;
@@ -948,8 +954,10 @@
 				addr = simple_strtoul(argv[1], NULL, 16);
 			else
 				addr = CONFIG_SYS_LOAD_ADDR;
-			return nand_load_image(cmdtp, nand_info[dev->id->num],
-					       part->offset, addr, argv[0]);
+
+			mtd = get_nand_dev_by_index(dev->id->num);
+			return nand_load_image(cmdtp, mtd, part->offset,
+					       addr, argv[0]);
 		}
 	}
 #endif
@@ -991,14 +999,15 @@
 
 	idx = simple_strtoul(boot_device, NULL, 16);
 
-	if (idx < 0 || idx >= CONFIG_SYS_MAX_NAND_DEVICE || !nand_info[idx]) {
+	mtd = get_nand_dev_by_index(idx);
+	if (!mtd) {
 		printf("\n** Device %d not available\n", idx);
 		bootstage_error(BOOTSTAGE_ID_NAND_AVAILABLE);
 		return 1;
 	}
 	bootstage_mark(BOOTSTAGE_ID_NAND_AVAILABLE);
 
-	return nand_load_image(cmdtp, nand_info[idx], offset, addr, argv[0]);
+	return nand_load_image(cmdtp, mtd, offset, addr, argv[0]);
 }
 
 U_BOOT_CMD(nboot, 4, 1, do_nandboot,
diff --git a/common/env_nand.c b/common/env_nand.c
index 2e28171..133ecfb 100644
--- a/common/env_nand.c
+++ b/common/env_nand.c
@@ -130,17 +130,22 @@
 	size_t end = offset + CONFIG_ENV_RANGE;
 	size_t amount_saved = 0;
 	size_t blocksize, len;
+	struct mtd_info *mtd;
 	u_char *char_ptr;
 
-	blocksize = nand_info[0]->erasesize;
+	mtd = get_nand_dev_by_index(0);
+	if (!mtd)
+		return 1;
+
+	blocksize = mtd->erasesize;
 	len = min(blocksize, (size_t)CONFIG_ENV_SIZE);
 
 	while (amount_saved < CONFIG_ENV_SIZE && offset < end) {
-		if (nand_block_isbad(nand_info[0], offset)) {
+		if (nand_block_isbad(mtd, offset)) {
 			offset += blocksize;
 		} else {
 			char_ptr = &buf[amount_saved];
-			if (nand_write(nand_info[0], offset, &len, char_ptr))
+			if (nand_write(mtd, offset, &len, char_ptr))
 				return 1;
 
 			offset += blocksize;
@@ -161,13 +166,15 @@
 static int erase_and_write_env(const struct env_location *location,
 		u_char *env_new)
 {
+	struct mtd_info *mtd;
 	int ret = 0;
 
-	if (!nand_info[0])
+	mtd = get_nand_dev_by_index(0);
+	if (!mtd)
 		return 1;
 
 	printf("Erasing %s...\n", location->name);
-	if (nand_erase_opts(nand_info[0], &location->erase_opts))
+	if (nand_erase_opts(mtd, &location->erase_opts))
 		return 1;
 
 	printf("Writing to %s... ", location->name);
@@ -248,22 +255,24 @@
 	size_t end = offset + CONFIG_ENV_RANGE;
 	size_t amount_loaded = 0;
 	size_t blocksize, len;
+	struct mtd_info *mtd;
 	u_char *char_ptr;
 
-	if (!nand_info[0])
+	mtd = get_nand_dev_by_index(0);
+	if (!mtd)
 		return 1;
 
-	blocksize = nand_info[0]->erasesize;
+	blocksize = mtd->erasesize;
 	len = min(blocksize, (size_t)CONFIG_ENV_SIZE);
 
 	while (amount_loaded < CONFIG_ENV_SIZE && offset < end) {
-		if (nand_block_isbad(nand_info[0], offset)) {
+		if (nand_block_isbad(mtd, offset)) {
 			offset += blocksize;
 		} else {
 			char_ptr = &buf[amount_loaded];
-			if (nand_read_skip_bad(nand_info[0], offset,
+			if (nand_read_skip_bad(mtd, offset,
 					       &len, NULL,
-					       nand_info[0]->size, char_ptr))
+					       mtd->size, char_ptr))
 				return 1;
 
 			offset += blocksize;
@@ -390,12 +399,12 @@
 	ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE);
 
 #if defined(CONFIG_ENV_OFFSET_OOB)
+	struct mtd_info *mtd  = get_nand_dev_by_index(0);
 	/*
 	 * If unable to read environment offset from NAND OOB then fall through
 	 * to the normal environment reading code below
 	 */
-	if (nand_info[0] && !get_nand_env_oob(nand_info[0],
-					      &nand_env_oob_offset)) {
+	if (mtd && !get_nand_env_oob(mtd, &nand_env_oob_offset)) {
 		printf("Found Environment offset in OOB..\n");
 	} else {
 		set_default_env("!no env offset in OOB");
diff --git a/common/fb_nand.c b/common/fb_nand.c
index c8c79e9..3d027d4 100644
--- a/common/fb_nand.c
+++ b/common/fb_nand.c
@@ -59,7 +59,7 @@
 		return -EINVAL;
 	}
 
-	*mtd = nand_info[dev->id->num];
+	*mtd = get_nand_dev_by_index(dev->id->num);
 
 	return 0;
 }
diff --git a/common/splash_source.c b/common/splash_source.c
index ee055dd..867a798 100644
--- a/common/splash_source.c
+++ b/common/splash_source.c
@@ -47,9 +47,10 @@
 #ifdef CONFIG_CMD_NAND
 static int splash_nand_read_raw(u32 bmp_load_addr, int offset, size_t read_size)
 {
-	return nand_read_skip_bad(nand_info[nand_curr_device], offset,
+	struct mtd_info *mtd = get_nand_dev_by_index(nand_curr_device);
+	return nand_read_skip_bad(mtd, offset,
 				  &read_size, NULL,
-				  nand_info[nand_curr_device]->size,
+				  mtd->size,
 				  (u_char *)bmp_load_addr);
 }
 #else
diff --git a/configs/am335x_boneblack_defconfig b/configs/am335x_boneblack_defconfig
index 3d86c1b..c698677 100644
--- a/configs/am335x_boneblack_defconfig
+++ b/configs/am335x_boneblack_defconfig
@@ -17,8 +17,13 @@
 CONFIG_AUTOBOOT_PROMPT="Press SPACE to abort autoboot in %d seconds\n"
 CONFIG_AUTOBOOT_DELAY_STR="d"
 CONFIG_AUTOBOOT_STOP_STR=" "
+CONFIG_FASTBOOT=y
+CONFIG_USB_FUNCTION_FASTBOOT=y
+CONFIG_FASTBOOT_BUF_ADDR=0x81000000
+CONFIG_FASTBOOT_BUF_SIZE=0x07000000
 # CONFIG_CMD_IMLS is not set
 # CONFIG_CMD_FLASH is not set
+CONFIG_CMD_FASTBOOT=y
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_DFU_TFTP=y
 CONFIG_DFU_MMC=y
diff --git a/configs/am335x_boneblack_vboot_defconfig b/configs/am335x_boneblack_vboot_defconfig
index ef5a3f1..b11d0a7 100644
--- a/configs/am335x_boneblack_vboot_defconfig
+++ b/configs/am335x_boneblack_vboot_defconfig
@@ -20,6 +20,10 @@
 CONFIG_AUTOBOOT_PROMPT="Press SPACE to abort autoboot in %d seconds\n"
 CONFIG_AUTOBOOT_DELAY_STR="d"
 CONFIG_AUTOBOOT_STOP_STR=" "
+CONFIG_FASTBOOT=y
+CONFIG_USB_FUNCTION_FASTBOOT=y
+CONFIG_FASTBOOT_BUF_ADDR=0x81000000
+CONFIG_FASTBOOT_BUF_SIZE=0x07000000
 # CONFIG_CMD_IMLS is not set
 # CONFIG_CMD_FLASH is not set
 # CONFIG_CMD_SETEXPR is not set
diff --git a/configs/am335x_evm_defconfig b/configs/am335x_evm_defconfig
index 19d5eff..4591c20 100644
--- a/configs/am335x_evm_defconfig
+++ b/configs/am335x_evm_defconfig
@@ -15,6 +15,10 @@
 CONFIG_SPL_MTD_SUPPORT=y
 CONFIG_SPL_MUSB_NEW_SUPPORT=y
 CONFIG_SPL_OS_BOOT=y
+CONFIG_FASTBOOT=y
+CONFIG_USB_FUNCTION_FASTBOOT=y
+CONFIG_FASTBOOT_BUF_ADDR=0x81000000
+CONFIG_FASTBOOT_BUF_SIZE=0x07000000
 # CONFIG_CMD_IMLS is not set
 # CONFIG_CMD_FLASH is not set
 # CONFIG_CMD_SETEXPR is not set
diff --git a/configs/am335x_evm_nor_defconfig b/configs/am335x_evm_nor_defconfig
index d038eb3..07beba6 100644
--- a/configs/am335x_evm_nor_defconfig
+++ b/configs/am335x_evm_nor_defconfig
@@ -13,6 +13,11 @@
 CONFIG_SPL_MTD_SUPPORT=y
 CONFIG_SPL_MUSB_NEW_SUPPORT=y
 CONFIG_SPL_OS_BOOT=y
+CONFIG_FASTBOOT=y
+CONFIG_USB_FUNCTION_FASTBOOT=y
+CONFIG_CMD_FASTBOOT=y
+CONFIG_FASTBOOT_BUF_ADDR=0x81000000
+CONFIG_FASTBOOT_BUF_SIZE=0x07000000
 # CONFIG_CMD_IMLS is not set
 CONFIG_CMD_ASKENV=y
 CONFIG_CMD_EEPROM=y
diff --git a/configs/am335x_evm_norboot_defconfig b/configs/am335x_evm_norboot_defconfig
index 2f96627..7e80c56 100644
--- a/configs/am335x_evm_norboot_defconfig
+++ b/configs/am335x_evm_norboot_defconfig
@@ -10,6 +10,10 @@
 CONFIG_VERSION_VARIABLE=y
 CONFIG_ARCH_MISC_INIT=y
 CONFIG_BOARD_EARLY_INIT_F=y
+CONFIG_FASTBOOT=y
+CONFIG_USB_FUNCTION_FASTBOOT=y
+CONFIG_FASTBOOT_BUF_ADDR=0x81000000
+CONFIG_FASTBOOT_BUF_SIZE=0x07000000
 # CONFIG_CMD_IMLS is not set
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_DFU_MMC=y
diff --git a/configs/am335x_evm_spiboot_defconfig b/configs/am335x_evm_spiboot_defconfig
index 40c165d..562c048 100644
--- a/configs/am335x_evm_spiboot_defconfig
+++ b/configs/am335x_evm_spiboot_defconfig
@@ -15,6 +15,10 @@
 CONFIG_SPL=y
 CONFIG_SPL_STACK_R=y
 CONFIG_SPL_MUSB_NEW_SUPPORT=y
+CONFIG_FASTBOOT=y
+CONFIG_USB_FUNCTION_FASTBOOT=y
+CONFIG_FASTBOOT_BUF_ADDR=0x81000000
+CONFIG_FASTBOOT_BUF_SIZE=0x07000000
 # CONFIG_CMD_IMLS is not set
 # CONFIG_CMD_FLASH is not set
 # CONFIG_CMD_SETEXPR is not set
diff --git a/configs/am335x_evm_usbspl_defconfig b/configs/am335x_evm_usbspl_defconfig
index ffd730e..7809786 100644
--- a/configs/am335x_evm_usbspl_defconfig
+++ b/configs/am335x_evm_usbspl_defconfig
@@ -17,6 +17,10 @@
 CONFIG_SPL_USB_GADGET_SUPPORT=y
 CONFIG_SPL_USBETH_SUPPORT=y
 # CONFIG_SPL_YMODEM_SUPPORT is not set
+CONFIG_FASTBOOT=y
+CONFIG_USB_FUNCTION_FASTBOOT=y
+CONFIG_FASTBOOT_BUF_ADDR=0x81000000
+CONFIG_FASTBOOT_BUF_SIZE=0x07000000
 # CONFIG_CMD_IMLS is not set
 # CONFIG_CMD_FLASH is not set
 # CONFIG_CMD_SETEXPR is not set
diff --git a/configs/am335x_hs_evm_defconfig b/configs/am335x_hs_evm_defconfig
index b0c88a6..8ad35c2 100644
--- a/configs/am335x_hs_evm_defconfig
+++ b/configs/am335x_hs_evm_defconfig
@@ -21,6 +21,7 @@
 CONFIG_SPL_MTD_SUPPORT=y
 # CONFIG_SPL_YMODEM_SUPPORT is not set
 # CONFIG_CMD_IMLS is not set
+CONFIG_CMD_FASTBOOT=y
 # CONFIG_CMD_FLASH is not set
 # CONFIG_CMD_SETEXPR is not set
 # CONFIG_SPL_EFI_PARTITION is not set
@@ -46,6 +47,7 @@
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_USB_MUSB_TI=y
 CONFIG_USB_STORAGE=y
+CONFIG_USB_FUNCTION_FASTBOOT=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_DOWNLOAD=y
 CONFIG_G_DNL_MANUFACTURER="Texas Instruments"
diff --git a/configs/mvebu_db-88f7040-nand_defconfig b/configs/mvebu_db-88f7040-nand_defconfig
deleted file mode 100644
index 2aba8de..0000000
--- a/configs/mvebu_db-88f7040-nand_defconfig
+++ /dev/null
@@ -1,72 +0,0 @@
-CONFIG_ARM=y
-CONFIG_ARCH_MVEBU=y
-CONFIG_SYS_MALLOC_F_LEN=0x2000
-CONFIG_TARGET_MVEBU_ARMADA_8K=y
-CONFIG_DEFAULT_DEVICE_TREE="armada-7040-db-nand"
-CONFIG_SMBIOS_PRODUCT_NAME=""
-CONFIG_DEBUG_UART=y
-CONFIG_AHCI=y
-# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SYS_CONSOLE_INFO_QUIET=y
-# CONFIG_DISPLAY_CPUINFO is not set
-# CONFIG_DISPLAY_BOARDINFO is not set
-CONFIG_ARCH_EARLY_INIT_R=y
-CONFIG_BOARD_EARLY_INIT_F=y
-CONFIG_HUSH_PARSER=y
-# CONFIG_CMD_IMLS is not set
-# CONFIG_CMD_FLASH is not set
-CONFIG_CMD_MMC=y
-CONFIG_CMD_NAND=y
-CONFIG_CMD_PART=y
-CONFIG_CMD_SF=y
-CONFIG_CMD_SPI=y
-CONFIG_CMD_I2C=y
-CONFIG_CMD_USB=y
-# CONFIG_CMD_FPGA is not set
-# CONFIG_CMD_SETEXPR is not set
-CONFIG_CMD_TFTPPUT=y
-CONFIG_CMD_DHCP=y
-CONFIG_CMD_MII=y
-CONFIG_CMD_PING=y
-CONFIG_CMD_CACHE=y
-CONFIG_CMD_TIME=y
-CONFIG_CMD_MVEBU_BUBT=y
-CONFIG_MVEBU_NAND_BOOT=y
-CONFIG_CMD_EXT4=y
-CONFIG_CMD_EXT4_WRITE=y
-CONFIG_CMD_FAT=y
-CONFIG_CMD_FS_GENERIC=y
-CONFIG_MAC_PARTITION=y
-CONFIG_ISO_PARTITION=y
-CONFIG_EFI_PARTITION=y
-CONFIG_BLOCK_CACHE=y
-CONFIG_DM_I2C=y
-CONFIG_SYS_I2C_MVTWSI=y
-CONFIG_MISC=y
-CONFIG_DM_MMC=y
-CONFIG_MMC_SDHCI=y
-CONFIG_MMC_SDHCI_XENON=y
-CONFIG_NAND_PXA3XX=y
-CONFIG_SPI_FLASH=y
-CONFIG_SPI_FLASH_MACRONIX=y
-CONFIG_SPI_FLASH_SPANSION=y
-CONFIG_SPI_FLASH_STMICRO=y
-CONFIG_PHYLIB=y
-CONFIG_PCI=y
-CONFIG_DM_PCI=y
-CONFIG_PCIE_DW_MVEBU=y
-CONFIG_MVEBU_COMPHY_SUPPORT=y
-CONFIG_PINCTRL=y
-CONFIG_PINCTRL_ARMADA_8K=y
-# CONFIG_SPL_SERIAL_PRESENT is not set
-CONFIG_DEBUG_UART_BASE=0xf0512000
-CONFIG_DEBUG_UART_CLOCK=200000000
-CONFIG_DEBUG_UART_SHIFT=2
-CONFIG_DEBUG_UART_ANNOUNCE=y
-CONFIG_SYS_NS16550=y
-CONFIG_USB=y
-CONFIG_DM_USB=y
-CONFIG_USB_XHCI_HCD=y
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_STORAGE=y
-CONFIG_SMBIOS_MANUFACTURER=""
diff --git a/configs/mvebu_db-88f7040_defconfig b/configs/mvebu_db-88f7040_defconfig
deleted file mode 100644
index 28af643..0000000
--- a/configs/mvebu_db-88f7040_defconfig
+++ /dev/null
@@ -1,70 +0,0 @@
-CONFIG_ARM=y
-CONFIG_ARCH_MVEBU=y
-CONFIG_SYS_MALLOC_F_LEN=0x2000
-CONFIG_TARGET_MVEBU_ARMADA_8K=y
-CONFIG_DEFAULT_DEVICE_TREE="armada-7040-db"
-CONFIG_SMBIOS_PRODUCT_NAME=""
-CONFIG_DEBUG_UART=y
-CONFIG_AHCI=y
-# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_SYS_CONSOLE_INFO_QUIET=y
-# CONFIG_DISPLAY_CPUINFO is not set
-# CONFIG_DISPLAY_BOARDINFO is not set
-CONFIG_ARCH_EARLY_INIT_R=y
-CONFIG_BOARD_EARLY_INIT_F=y
-CONFIG_HUSH_PARSER=y
-# CONFIG_CMD_IMLS is not set
-# CONFIG_CMD_FLASH is not set
-CONFIG_CMD_MMC=y
-CONFIG_CMD_PART=y
-CONFIG_CMD_SF=y
-CONFIG_CMD_SPI=y
-CONFIG_CMD_I2C=y
-CONFIG_CMD_USB=y
-# CONFIG_CMD_FPGA is not set
-# CONFIG_CMD_SETEXPR is not set
-CONFIG_CMD_TFTPPUT=y
-CONFIG_CMD_DHCP=y
-CONFIG_CMD_MII=y
-CONFIG_CMD_PING=y
-CONFIG_CMD_CACHE=y
-CONFIG_CMD_TIME=y
-CONFIG_CMD_MVEBU_BUBT=y
-CONFIG_CMD_EXT4=y
-CONFIG_CMD_EXT4_WRITE=y
-CONFIG_CMD_FAT=y
-CONFIG_CMD_FS_GENERIC=y
-CONFIG_MAC_PARTITION=y
-CONFIG_ISO_PARTITION=y
-CONFIG_EFI_PARTITION=y
-CONFIG_BLOCK_CACHE=y
-CONFIG_DM_I2C=y
-CONFIG_SYS_I2C_MVTWSI=y
-CONFIG_MISC=y
-CONFIG_DM_MMC=y
-CONFIG_MMC_SDHCI=y
-CONFIG_MMC_SDHCI_XENON=y
-CONFIG_SPI_FLASH=y
-CONFIG_SPI_FLASH_MACRONIX=y
-CONFIG_SPI_FLASH_SPANSION=y
-CONFIG_SPI_FLASH_STMICRO=y
-CONFIG_PHY_MARVELL=y
-CONFIG_MVPP2=y
-CONFIG_PCI=y
-CONFIG_DM_PCI=y
-CONFIG_PCIE_DW_MVEBU=y
-CONFIG_MVEBU_COMPHY_SUPPORT=y
-CONFIG_PINCTRL=y
-CONFIG_PINCTRL_ARMADA_8K=y
-# CONFIG_SPL_SERIAL_PRESENT is not set
-CONFIG_DEBUG_UART_BASE=0xf0512000
-CONFIG_DEBUG_UART_CLOCK=200000000
-CONFIG_DEBUG_UART_SHIFT=2
-CONFIG_DEBUG_UART_ANNOUNCE=y
-CONFIG_SYS_NS16550=y
-CONFIG_USB=y
-CONFIG_DM_USB=y
-CONFIG_USB_XHCI_HCD=y
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_STORAGE=y
-CONFIG_SMBIOS_MANUFACTURER=""
diff --git a/configs/mvebu_db-88f8040_defconfig b/configs/mvebu_db_armada8k_defconfig
similarity index 100%
rename from configs/mvebu_db-88f8040_defconfig
rename to configs/mvebu_db_armada8k_defconfig
diff --git a/configs/ti816x_evm_defconfig b/configs/ti816x_evm_defconfig
index 1c66082..2ae72b2 100644
--- a/configs/ti816x_evm_defconfig
+++ b/configs/ti816x_evm_defconfig
@@ -27,6 +27,7 @@
 CONFIG_CMD_MMC=y
 CONFIG_CMD_I2C=y
 # CONFIG_CMD_FPGA is not set
+CONFIG_CMD_GPIO=y
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_EXT4_WRITE=y
 # CONFIG_ISO_PARTITION is not set
@@ -35,6 +36,11 @@
 CONFIG_DM=y
 CONFIG_DM_GPIO=y
 CONFIG_DM_I2C=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_FAT=y
 CONFIG_MMC_OMAP_HS=y
 CONFIG_SYS_NS16550=y
 # CONFIG_USE_PRIVATE_LIBGCC is not set
diff --git a/configs/turris_omnia_defconfig b/configs/turris_omnia_defconfig
new file mode 100644
index 0000000..512b9da
--- /dev/null
+++ b/configs/turris_omnia_defconfig
@@ -0,0 +1,62 @@
+CONFIG_ARM=y
+CONFIG_ARCH_MVEBU=y
+CONFIG_SPL_LIBCOMMON_SUPPORT=y
+CONFIG_SPL_LIBGENERIC_SUPPORT=y
+CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_TARGET_TURRIS_OMNIA=y
+CONFIG_SPL_SERIAL_SUPPORT=y
+CONFIG_SPL_SPI_FLASH_SUPPORT=y
+CONFIG_SPL_SPI_SUPPORT=y
+CONFIG_SPL_BOOT_DEVICE_SPI=y
+CONFIG_DISTRO_DEFAULTS=y
+CONFIG_DEFAULT_DEVICE_TREE="armada-385-turris-omnia"
+CONFIG_BOOTDELAY=3
+CONFIG_SYS_CONSOLE_INFO_QUIET=y
+CONFIG_SPL=y
+CONFIG_SPL_I2C_SUPPORT=y
+# CONFIG_CMD_IMLS is not set
+# CONFIG_CMD_FLASH is not set
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_USB=y
+CONFIG_CMD_TFTPPUT=y
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_TIME=y
+CONFIG_CMD_GO=y
+CONFIG_CMD_RUN=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_SAVEENV=y
+CONFIG_CMD_LOADB=y
+CONFIG_CMD_LOADS=y
+CONFIG_CMD_MEMORY=y
+CONFIG_CMD_ECHO=y
+CONFIG_CMD_SETEXPR=y
+# CONFIG_PARTITION_UUIDS is not set
+# CONFIG_SPL_PARTITION_UUIDS is not set
+CONFIG_DOS_PARTITION=y
+CONFIG_SPL_OF_TRANSLATE=y
+CONFIG_MISC=y
+CONFIG_ATSHA204A=y
+CONFIG_DEBUG_UART=y
+CONFIG_DEBUG_UART_NS16550=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_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_MV=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI=y
+CONFIG_USB_EHCI_MARVELL=y
+CONFIG_USB_STORAGE=y
+CONFIG_WDT=y
+CONFIG_WDT_ORION=y
+CONFIG_ARCH_MISC_INIT=y
+CONFIG_BOARD_EARLY_INIT_F=y
+CONFIG_CMDLINE=y
+CONFIG_HUSH_PARSER=y
+CONFIG_SYS_PROMPT="=> "
+# CONFIG_DISPLAY_BOARDINFO is not set
diff --git a/doc/README.marvell b/doc/README.marvell
new file mode 100644
index 0000000..3364617
--- /dev/null
+++ b/doc/README.marvell
@@ -0,0 +1,53 @@
+Marvell U-Boot Build Instructions
+=================================
+
+This document describes how to compile the U-Boot and how to change U-Boot configuration
+
+Build Procedure
+----------------
+1. Install required packages:
+
+		# sudo apt-get install libssl-dev
+		# sudo apt-get install device-tree-compiler
+		# sudo apt-get install swig libpython-dev
+
+2. Set the cross compiler:
+
+		# export CROSS_COMPILE=/path/to/toolchain/aarch64-marvell-linux-gnu-
+
+3. Clean-up old residuals:
+
+		# make mrproper
+
+4. Configure the U-Boot:
+
+		# make <defconfig_file>
+
+	- For the Armada-70x0/80x0 DB board use "mvebu_db_armada8k_defconfig"
+	- For the Armada-80x0 MacchiatoBin use "make mvebu_mcbin-88f8040_defconfig"
+	- For the Armada-3700 DB board use "make mvebu_db-88f3720_defconfig"
+	- For the Armada-3700 EsspressoBin use "make mvebu_espressobin-88f3720_defconfig"
+
+5. Configure the device-tree and build the U-Boot image:
+
+	Compile u-boot and set the required device-tree using:
+
+		# make DEVICE_TREE=<name>
+
+	NOTE:
+	Compilation with "mvebu_db_armada8k_defconfig" requires explicitly exporting DEVICE_TREE
+	for the requested board.
+	By default, u-boot is compiled with armada-8040-db device-tree.
+        Using A80x0 device-tree on A70x0 might break the device.
+        In order to prevent this, the required device-tree MUST be set during compilation.
+        All device-tree files are located in ./arch/arm/dts/ folder.
+
+	NOTE:
+	The u-boot.bin should not be used as a stand-alone image.
+	The ARM Trusted Firmware (ATF) build process uses this image to generate the
+	flash image.
+
+Configuration update
+---------------------
+	To update the U-Boot configuration, please refer to doc/README.kconfig
+
diff --git a/drivers/ddr/marvell/a38x/ddr3_training.c b/drivers/ddr/marvell/a38x/ddr3_training.c
index 7e0749f..e70ca4b 100644
--- a/drivers/ddr/marvell/a38x/ddr3_training.c
+++ b/drivers/ddr/marvell/a38x/ddr3_training.c
@@ -308,6 +308,7 @@
 	enum hws_speed_bin speed_bin_index = SPEED_BIN_DDR_2133N;
 	enum hws_mem_size memory_size = MEM_2G;
 	enum hws_ddr_freq freq = init_freq;
+	enum hws_timing timing;
 	u32 cs_mask = 0;
 	u32 cl_value = 0, cwl_val = 0;
 	u32 refresh_interval_cnt = 0, bus_cnt = 0, adll_tap = 0;
@@ -569,8 +570,13 @@
 				      DUNIT_CONTROL_HIGH_REG,
 				      (init_cntr_prm->msys_init << 7), (1 << 7)));
 
+			timing = tm->interface_params[if_id].timing;
+
 			if (mode2_t != 0xff) {
 				t2t = mode2_t;
+			} else if (timing != HWS_TIM_DEFAULT) {
+				/* Board topology map is forcing timing */
+				t2t = (timing == HWS_TIM_2T) ? 1 : 0;
 			} else {
 				/* calculate number of CS (per interface) */
 				CHECK_STATUS(calc_cs_num
diff --git a/drivers/ddr/marvell/a38x/ddr_topology_def.h b/drivers/ddr/marvell/a38x/ddr_topology_def.h
index f8894e8..229c3a1 100644
--- a/drivers/ddr/marvell/a38x/ddr_topology_def.h
+++ b/drivers/ddr/marvell/a38x/ddr_topology_def.h
@@ -37,6 +37,12 @@
 	MEM_SIZE_LAST
 };
 
+enum hws_timing {
+	HWS_TIM_DEFAULT,
+	HWS_TIM_1T,
+	HWS_TIM_2T
+};
+
 struct bus_params {
 	/* Chip Select (CS) bitmask (bits 0-CS0, bit 1- CS1 ...) */
 	u8 cs_bitmask;
@@ -84,6 +90,9 @@
 
 	/* operation temperature */
 	enum hws_temperature interface_temp;
+
+	/* 2T vs 1T mode (by default computed from number of CSs) */
+	enum hws_timing timing;
 };
 
 struct hws_topology_map {
diff --git a/drivers/dfu/dfu_nand.c b/drivers/dfu/dfu_nand.c
index 23f1571..97cd608 100644
--- a/drivers/dfu/dfu_nand.c
+++ b/drivers/dfu/dfu_nand.c
@@ -37,15 +37,15 @@
 	lim = dfu->data.nand.start + dfu->data.nand.size - start;
 	count = *len;
 
+	mtd = get_nand_dev_by_index(nand_curr_device);
+
 	if (nand_curr_device < 0 ||
 	    nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE ||
-	    !nand_info[nand_curr_device]) {
+	    !mtd) {
 		printf("%s: invalid nand device\n", __func__);
 		return -1;
 	}
 
-	mtd = nand_info[nand_curr_device];
-
 	if (op == DFU_OP_READ) {
 		ret = nand_read_skip_bad(mtd, start, &count, &actual,
 					 lim, buf);
@@ -143,18 +143,16 @@
 
 	/* in case of ubi partition, erase rest of the partition */
 	if (dfu->data.nand.ubi) {
-		struct mtd_info *mtd;
+		struct mtd_info *mtd = get_nand_dev_by_index(nand_curr_device);
 		nand_erase_options_t opts;
 
 		if (nand_curr_device < 0 ||
 		    nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE ||
-		    !nand_info[nand_curr_device]) {
+		    !mtd) {
 			printf("%s: invalid nand device\n", __func__);
 			return -1;
 		}
 
-		mtd = nand_info[nand_curr_device];
-
 		memset(&opts, 0, sizeof(opts));
 		off = dfu->offset;
 		if ((off & (mtd->erasesize - 1)) != 0) {
diff --git a/drivers/i2c/muxes/pca954x.c b/drivers/i2c/muxes/pca954x.c
index 1a67618..383f72f 100644
--- a/drivers/i2c/muxes/pca954x.c
+++ b/drivers/i2c/muxes/pca954x.c
@@ -13,11 +13,40 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+enum pca_type {
+	PCA9544,
+	PCA9547,
+	PCA9548
+};
+
+struct chip_desc {
+	u8 enable;
+	enum muxtype {
+		pca954x_ismux = 0,
+		pca954x_isswi,
+	} muxtype;
+};
+
 struct pca954x_priv {
 	u32 addr; /* I2C mux address */
 	u32 width; /* I2C mux width - number of busses */
 };
 
+static const struct chip_desc chips[] = {
+	[PCA9544] = {
+		.enable = 0x4,
+		.muxtype = pca954x_ismux,
+	},
+	[PCA9547] = {
+		.enable = 0x8,
+		.muxtype = pca954x_ismux,
+	},
+	[PCA9548] = {
+		.enable = 0x8,
+		.muxtype = pca954x_isswi,
+	},
+};
+
 static int pca954x_deselect(struct udevice *mux, struct udevice *bus,
 			    uint channel)
 {
@@ -31,7 +60,13 @@
 			  uint channel)
 {
 	struct pca954x_priv *priv = dev_get_priv(mux);
-	uchar byte = 1 << channel;
+	const struct chip_desc *chip = &chips[dev_get_driver_data(mux)];
+	uchar byte;
+
+	if (chip->muxtype == pca954x_ismux)
+		byte = channel | chip->enable;
+	else
+		byte = 1 << channel;
 
 	return dm_i2c_write(mux, priv->addr, &byte, 1);
 }
@@ -42,8 +77,9 @@
 };
 
 static const struct udevice_id pca954x_ids[] = {
-	{ .compatible = "nxp,pca9548", .data = (ulong)8 },
-	{ .compatible = "nxp,pca9544", .data = (ulong)4 },
+	{ .compatible = "nxp,pca9544", .data = PCA9544 },
+	{ .compatible = "nxp,pca9547", .data = PCA9547 },
+	{ .compatible = "nxp,pca9548", .data = PCA9548 },
 	{ }
 };
 
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 92f348f..d1ddbbe 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -20,6 +20,14 @@
 	  Select this to enable a sysid for Altera devices. Please find
 	  details on the "Embedded Peripherals IP User Guide" of Altera.
 
+config ATSHA204A
+	bool "Support for Atmel ATSHA204A module"
+	depends on MISC
+	help
+	   Enable support for I2C connected Atmel's ATSHA204A
+	   CryptoAuthentication module found for example on the Turris Omnia
+	   board.
+
 config ROCKCHIP_EFUSE
         bool "Rockchip e-fuse support"
 	depends on MISC
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index ea64677..10265c8 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -8,6 +8,7 @@
 obj-$(CONFIG_MISC) += misc-uclass.o
 obj-$(CONFIG_ALI152X) += ali512x.o
 obj-$(CONFIG_ALTERA_SYSID) += altera_sysid.o
+obj-$(CONFIG_ATSHA204A) += atsha204a-i2c.o
 obj-$(CONFIG_DS4510)  += ds4510.o
 obj-$(CONFIG_CBMEM_CONSOLE) += cbmem_console.o
 ifndef CONFIG_SPL_BUILD
diff --git a/drivers/misc/atsha204a-i2c.c b/drivers/misc/atsha204a-i2c.c
new file mode 100644
index 0000000..934ba5e
--- /dev/null
+++ b/drivers/misc/atsha204a-i2c.c
@@ -0,0 +1,408 @@
+/*
+ * I2C Driver for Atmel ATSHA204 over I2C
+ *
+ * Copyright (C) 2014 Josh Datko, Cryptotronix, jbd@cryptotronix.com
+ * 		 2016 Tomas Hlavacek, CZ.NIC, tmshlvck@gmail.com
+ * 		 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <i2c.h>
+#include <errno.h>
+#include <atsha204a-i2c.h>
+
+#define ATSHA204A_TWLO			60
+#define ATSHA204A_TRANSACTION_TIMEOUT	100000
+#define ATSHA204A_TRANSACTION_RETRY	5
+#define ATSHA204A_EXECTIME		5000
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * The ATSHA204A uses an (to me) unknown CRC-16 algorithm.
+ * The Reveng CRC-16 catalogue does not contain it.
+ *
+ * Because in Atmel's documentation only a primitive implementation
+ * can be found, I have implemented this one with lookup table.
+ */
+
+/*
+ * This is the code that computes the table below:
+ *
+ * int i, j;
+ * for (i = 0; i < 256; ++i) {
+ * 	u8 c = 0;
+ * 	for (j = 0; j < 8; ++j) {
+ * 		c = (c << 1) | ((i >> j) & 1);
+ * 	}
+ * 	bitreverse_table[i] = c;
+ * }
+ */
+
+static u8 const bitreverse_table[256] = {
+	0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
+	0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
+	0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
+	0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
+	0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
+	0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
+	0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
+	0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
+	0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
+	0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
+	0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
+	0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
+	0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
+	0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
+	0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
+	0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
+	0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
+	0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
+	0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
+	0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
+	0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
+	0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
+	0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
+	0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
+	0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
+	0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
+	0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
+	0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
+	0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
+	0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
+	0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
+	0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
+};
+
+/*
+ * This is the code that computes the table below:
+ *
+ * int i, j;
+ * for (i = 0; i < 256; ++i) {
+ * 	u16 c = i << 8;
+ * 	for (j = 0; j < 8; ++j) {
+ * 		int b = c >> 15;
+ * 		c <<= 1;
+ * 		if (b)
+ * 			c ^= 0x8005;
+ * 	}
+ * 	crc16_table[i] = c;
+ * }
+ */
+static u16 const crc16_table[256] = {
+	0x0000, 0x8005, 0x800f, 0x000a, 0x801b, 0x001e, 0x0014, 0x8011,
+	0x8033, 0x0036, 0x003c, 0x8039, 0x0028, 0x802d, 0x8027, 0x0022,
+	0x8063, 0x0066, 0x006c, 0x8069, 0x0078, 0x807d, 0x8077, 0x0072,
+	0x0050, 0x8055, 0x805f, 0x005a, 0x804b, 0x004e, 0x0044, 0x8041,
+	0x80c3, 0x00c6, 0x00cc, 0x80c9, 0x00d8, 0x80dd, 0x80d7, 0x00d2,
+	0x00f0, 0x80f5, 0x80ff, 0x00fa, 0x80eb, 0x00ee, 0x00e4, 0x80e1,
+	0x00a0, 0x80a5, 0x80af, 0x00aa, 0x80bb, 0x00be, 0x00b4, 0x80b1,
+	0x8093, 0x0096, 0x009c, 0x8099, 0x0088, 0x808d, 0x8087, 0x0082,
+	0x8183, 0x0186, 0x018c, 0x8189, 0x0198, 0x819d, 0x8197, 0x0192,
+	0x01b0, 0x81b5, 0x81bf, 0x01ba, 0x81ab, 0x01ae, 0x01a4, 0x81a1,
+	0x01e0, 0x81e5, 0x81ef, 0x01ea, 0x81fb, 0x01fe, 0x01f4, 0x81f1,
+	0x81d3, 0x01d6, 0x01dc, 0x81d9, 0x01c8, 0x81cd, 0x81c7, 0x01c2,
+	0x0140, 0x8145, 0x814f, 0x014a, 0x815b, 0x015e, 0x0154, 0x8151,
+	0x8173, 0x0176, 0x017c, 0x8179, 0x0168, 0x816d, 0x8167, 0x0162,
+	0x8123, 0x0126, 0x012c, 0x8129, 0x0138, 0x813d, 0x8137, 0x0132,
+	0x0110, 0x8115, 0x811f, 0x011a, 0x810b, 0x010e, 0x0104, 0x8101,
+	0x8303, 0x0306, 0x030c, 0x8309, 0x0318, 0x831d, 0x8317, 0x0312,
+	0x0330, 0x8335, 0x833f, 0x033a, 0x832b, 0x032e, 0x0324, 0x8321,
+	0x0360, 0x8365, 0x836f, 0x036a, 0x837b, 0x037e, 0x0374, 0x8371,
+	0x8353, 0x0356, 0x035c, 0x8359, 0x0348, 0x834d, 0x8347, 0x0342,
+	0x03c0, 0x83c5, 0x83cf, 0x03ca, 0x83db, 0x03de, 0x03d4, 0x83d1,
+	0x83f3, 0x03f6, 0x03fc, 0x83f9, 0x03e8, 0x83ed, 0x83e7, 0x03e2,
+	0x83a3, 0x03a6, 0x03ac, 0x83a9, 0x03b8, 0x83bd, 0x83b7, 0x03b2,
+	0x0390, 0x8395, 0x839f, 0x039a, 0x838b, 0x038e, 0x0384, 0x8381,
+	0x0280, 0x8285, 0x828f, 0x028a, 0x829b, 0x029e, 0x0294, 0x8291,
+	0x82b3, 0x02b6, 0x02bc, 0x82b9, 0x02a8, 0x82ad, 0x82a7, 0x02a2,
+	0x82e3, 0x02e6, 0x02ec, 0x82e9, 0x02f8, 0x82fd, 0x82f7, 0x02f2,
+	0x02d0, 0x82d5, 0x82df, 0x02da, 0x82cb, 0x02ce, 0x02c4, 0x82c1,
+	0x8243, 0x0246, 0x024c, 0x8249, 0x0258, 0x825d, 0x8257, 0x0252,
+	0x0270, 0x8275, 0x827f, 0x027a, 0x826b, 0x026e, 0x0264, 0x8261,
+	0x0220, 0x8225, 0x822f, 0x022a, 0x823b, 0x023e, 0x0234, 0x8231,
+	0x8213, 0x0216, 0x021c, 0x8219, 0x0208, 0x820d, 0x8207, 0x0202,
+};
+
+static inline u16 crc16_byte(u16 crc, const u8 data)
+{
+	u16 t = crc16_table[((crc >> 8) ^ bitreverse_table[data]) & 0xff];
+	return ((crc << 8) ^ t);
+}
+
+static u16 atsha204a_crc16(const u8 *buffer, size_t len)
+{
+	u16 crc = 0;
+
+	while (len--)
+		crc = crc16_byte(crc, *buffer++);
+
+	return cpu_to_le16(crc);
+}
+
+static int atsha204a_send(struct udevice *dev, const u8 *buf, u8 len)
+{
+	fdt_addr_t *priv = dev_get_priv(dev);
+	struct i2c_msg msg;
+
+	msg.addr = *priv;
+	msg.flags = I2C_M_STOP;
+	msg.len = len;
+	msg.buf = (u8 *) buf;
+
+	return dm_i2c_xfer(dev, &msg, 1);
+}
+
+static int atsha204a_recv(struct udevice *dev, u8 *buf, u8 len)
+{
+	fdt_addr_t *priv = dev_get_priv(dev);
+	struct i2c_msg msg;
+
+	msg.addr = *priv;
+	msg.flags = I2C_M_RD | I2C_M_STOP;
+	msg.len = len;
+	msg.buf = (u8 *) buf;
+
+	return dm_i2c_xfer(dev, &msg, 1);
+}
+
+static int atsha204a_recv_resp(struct udevice *dev,
+			       struct atsha204a_resp *resp)
+{
+	int res;
+	u16 resp_crc, computed_crc;
+	u8 *p = (u8 *) resp;
+
+	res = atsha204a_recv(dev, p, 4);
+	if (res)
+		return res;
+
+	if (resp->length > 4) {
+		if (resp->length > sizeof(*resp))
+			return -EMSGSIZE;
+
+		res = atsha204a_recv(dev, p + 4, resp->length - 4);
+		if (res)
+			return res;
+	}
+
+	resp_crc = (u16) p[resp->length - 2]
+		   | (((u16) p[resp->length - 1]) << 8);
+	computed_crc = atsha204a_crc16(p, resp->length - 2);
+
+	if (resp_crc != computed_crc) {
+		debug("Invalid checksum in ATSHA204A response\n");
+		return -EBADMSG;
+	}
+
+	return 0;
+}
+
+int atsha204a_wakeup(struct udevice *dev)
+{
+	u8 req[4];
+	struct atsha204a_resp resp;
+	int try, res;
+
+	debug("Waking up ATSHA204A\n");
+
+	for (try = 1; try <= 10; ++try) {
+		debug("Try %i... ", try);
+
+		memset(req, 0, 4);
+		res = atsha204a_send(dev, req, 4);
+		if (res) {
+			debug("failed on I2C send, trying again\n");
+			continue;
+		}
+
+		udelay(ATSHA204A_TWLO);
+
+		res = atsha204a_recv_resp(dev, &resp);
+		if (res) {
+			debug("failed on receiving response, ending\n");
+			return res;
+		}
+
+		if (resp.code != ATSHA204A_STATUS_AFTER_WAKE) {
+			debug ("failed (responce code = %02x), ending\n",
+			       resp.code);
+			return -EBADMSG;
+		}
+
+		debug("success\n");
+		break;
+	}
+
+	return 0;
+}
+
+int atsha204a_idle(struct udevice *dev)
+{
+	int res;
+	u8 req = ATSHA204A_FUNC_IDLE;
+
+	res = atsha204a_send(dev, &req, 1);
+	if (res)
+		debug("Failed putting ATSHA204A idle\n");
+	return res;
+}
+
+int atsha204a_sleep(struct udevice *dev)
+{
+	int res;
+	u8 req = ATSHA204A_FUNC_IDLE;
+
+	res = atsha204a_send(dev, &req, 1);
+	if (res)
+		debug("Failed putting ATSHA204A to sleep\n");
+	return res;
+}
+
+static int atsha204a_transaction(struct udevice *dev, struct atsha204a_req *req,
+				struct atsha204a_resp *resp)
+{
+	int res, timeout = ATSHA204A_TRANSACTION_TIMEOUT;
+
+	res = atsha204a_send(dev, (u8 *) req, req->length + 1);
+	if (res) {
+		debug("ATSHA204A transaction send failed\n");
+		return -EBUSY;
+	}
+
+	do {
+		res = atsha204a_recv_resp(dev, resp);
+		if (!res || res == -EMSGSIZE || res == -EBADMSG)
+			break;
+
+		debug("ATSHA204A transaction polling for response "
+		      "(timeout = %d)\n", timeout);
+
+		udelay(ATSHA204A_EXECTIME);
+		timeout -= ATSHA204A_EXECTIME;
+	} while (timeout > 0);
+
+	if (timeout <= 0) {
+		debug("ATSHA204A transaction timed out\n");
+		return -ETIMEDOUT;
+	}
+
+	return res;
+}
+
+static void atsha204a_req_crc32(struct atsha204a_req *req)
+{
+	u8 *p = (u8 *) req;
+	u16 computed_crc;
+	u16 *crc_ptr = (u16 *) &p[req->length - 1];
+
+	/* The buffer to crc16 starts at byte 1, not 0 */
+	computed_crc = atsha204a_crc16(p + 1, req->length - 2);
+
+	*crc_ptr = cpu_to_le16(computed_crc);
+}
+
+int atsha204a_read(struct udevice *dev, enum atsha204a_zone zone, bool read32,
+		  u16 addr, u8 *buffer)
+{
+	int res, retry = ATSHA204A_TRANSACTION_RETRY;
+	struct atsha204a_req req;
+	struct atsha204a_resp resp;
+
+	req.function = ATSHA204A_FUNC_COMMAND;
+	req.length = 7;
+	req.command = ATSHA204A_CMD_READ;
+
+	req.param1 = (u8) zone;
+	if (read32)
+		req.param1 |= 0x80;
+
+	req.param2 = cpu_to_le16(addr);
+
+	atsha204a_req_crc32(&req);
+
+	do {
+		res = atsha204a_transaction(dev, &req, &resp);
+		if (!res)
+			break;
+
+		debug("ATSHA204A read retry (%d)\n", retry);
+		retry--;
+		atsha204a_wakeup(dev);
+	} while (retry >= 0);
+	
+	if (res) {
+		debug("ATSHA204A read failed\n");
+		return res;
+	}
+
+	if (resp.length != (read32 ? 32 : 4) + 3) {
+		debug("ATSHA204A read bad response length (%d)\n",
+		      resp.length);
+		return -EBADMSG;
+	}
+
+	memcpy(buffer, ((u8 *) &resp) + 1, read32 ? 32 : 4);
+
+	return 0;
+}
+
+int atsha204a_get_random(struct udevice *dev, u8 *buffer, size_t max)
+{
+	int res;
+	struct atsha204a_req req;
+	struct atsha204a_resp resp;
+
+	req.function = ATSHA204A_FUNC_COMMAND;
+	req.length = 7;
+	req.command = ATSHA204A_CMD_RANDOM;
+
+	req.param1 = 1;
+	req.param2 = 0;
+
+	/* We do not have to compute the checksum dynamically */
+	req.data[0] = 0x27;
+	req.data[1] = 0x47;
+
+	res = atsha204a_transaction(dev, &req, &resp);
+	if (res) {
+		debug("ATSHA204A random transaction failed\n");
+		return res;
+	}
+
+	memcpy(buffer, ((u8 *) &resp) + 1, max >= 32 ? 32 : max);
+	return 0;
+}
+
+static int atsha204a_ofdata_to_platdata(struct udevice *dev)
+{
+	fdt_addr_t *priv = dev_get_priv(dev);
+	fdt_addr_t addr;
+
+	addr = fdtdec_get_addr(gd->fdt_blob, dev_of_offset(dev), "reg");
+	if (addr == FDT_ADDR_T_NONE) {
+		debug("Can't get ATSHA204A I2C base address\n");
+		return -ENXIO;
+	}
+
+	*priv = addr;
+	return 0;
+}
+
+static const struct udevice_id atsha204a_ids[] = {
+	{ .compatible = "atmel,atsha204a" },
+	{ }
+};
+
+U_BOOT_DRIVER(atsha204) = {
+	.name			= "atsha204",
+	.id			= UCLASS_MISC,
+	.of_match		= atsha204a_ids,
+	.ofdata_to_platdata	= atsha204a_ofdata_to_platdata,
+	.priv_auto_alloc_size	= sizeof(fdt_addr_t),
+};
diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c
index a1f2cba..d5d1056 100644
--- a/drivers/mtd/nand/fsmc_nand.c
+++ b/drivers/mtd/nand/fsmc_nand.c
@@ -409,7 +409,7 @@
 	 * Nomadik SoC is currently supporting this fsmc_nand_switch_ecc()
 	 * function, as it doesn't need to switch to a different ECC layout.
 	 */
-	mtd = nand_info[nand_curr_device];
+	mtd = get_nand_dev_by_index(nand_curr_device);
 	nand = mtd_to_nand(mtd);
 
 	/* Setup the ecc configurations again */
diff --git a/drivers/mtd/nand/nand.c b/drivers/mtd/nand/nand.c
index 168bac6..6aa909f 100644
--- a/drivers/mtd/nand/nand.c
+++ b/drivers/mtd/nand/nand.c
@@ -19,8 +19,7 @@
 
 int nand_curr_device = -1;
 
-
-struct mtd_info *nand_info[CONFIG_SYS_MAX_NAND_DEVICE];
+static struct mtd_info *nand_info[CONFIG_SYS_MAX_NAND_DEVICE];
 
 #ifndef CONFIG_SYS_NAND_SELF_INIT
 static struct nand_chip nand_chip[CONFIG_SYS_MAX_NAND_DEVICE];
@@ -31,12 +30,21 @@
 
 static unsigned long total_nand_size; /* in kiB */
 
+struct mtd_info *get_nand_dev_by_index(int dev)
+{
+	if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE || !nand_info[dev] ||
+	    !nand_info[dev]->name)
+		return NULL;
+
+	return nand_info[dev];
+}
+
 int nand_mtd_to_devnum(struct mtd_info *mtd)
 {
 	int i;
 
-	for (i = 0; i < ARRAY_SIZE(nand_info); i++) {
-		if (mtd && nand_info[i] == mtd)
+	for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) {
+		if (mtd && get_nand_dev_by_index(i) == mtd)
 			return i;
 	}
 
@@ -101,8 +109,9 @@
 	int i;
 
 	for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) {
-		if (nand_info[i] != NULL) {
-			nand_info_list[nand_devices_found] = nand_info[i];
+		struct mtd_info *mtd = get_nand_dev_by_index(i);
+		if (mtd != NULL) {
+			nand_info_list[nand_devices_found] = mtd;
 			nand_devices_found++;
 		}
 	}
@@ -161,7 +170,7 @@
 	/*
 	 * Select the chip in the board/cpu specific driver
 	 */
-	board_nand_select_device(mtd_to_nand(nand_info[nand_curr_device]),
+	board_nand_select_device(mtd_to_nand(get_nand_dev_by_index(nand_curr_device)),
 				 nand_curr_device);
 #endif
 
diff --git a/drivers/mtd/nand/omap_gpmc.c b/drivers/mtd/nand/omap_gpmc.c
index f4f0de3..b540bc3 100644
--- a/drivers/mtd/nand/omap_gpmc.c
+++ b/drivers/mtd/nand/omap_gpmc.c
@@ -894,17 +894,14 @@
 int __maybe_unused omap_nand_switch_ecc(uint32_t hardware, uint32_t eccstrength)
 {
 	struct nand_chip *nand;
-	struct mtd_info *mtd;
+	struct mtd_info *mtd = get_nand_dev_by_index(nand_curr_device);
 	int err = 0;
 
-	if (nand_curr_device < 0 ||
-	    nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE ||
-	    !nand_info[nand_curr_device]) {
+	if (!mtd) {
 		printf("nand: error: no NAND devices found\n");
 		return -ENODEV;
 	}
 
-	mtd = nand_info[nand_curr_device];
 	nand = mtd_to_nand(mtd);
 	nand->options |= NAND_OWN_BUFFERS;
 	nand->options &= ~NAND_SUBPAGE_READ;
diff --git a/drivers/mtd/nand/zynq_nand.c b/drivers/mtd/nand/zynq_nand.c
index cb3340d..948f059 100644
--- a/drivers/mtd/nand/zynq_nand.c
+++ b/drivers/mtd/nand/zynq_nand.c
@@ -1008,7 +1008,7 @@
 	}
 
 	xnand->nand_base = (void __iomem *)ZYNQ_NAND_BASEADDR;
-	mtd = (struct mtd_info *)&nand_info[0];
+	mtd = get_nand_dev_by_index(0);
 
 	nand_chip->priv = xnand;
 	mtd->priv = nand_chip;
diff --git a/drivers/net/fm/fm.c b/drivers/net/fm/fm.c
index 89f0d6a..9fe34ad 100644
--- a/drivers/net/fm/fm.c
+++ b/drivers/net/fm/fm.c
@@ -357,7 +357,8 @@
 	size_t fw_length = CONFIG_SYS_QE_FMAN_FW_LENGTH;
 	void *addr = malloc(CONFIG_SYS_QE_FMAN_FW_LENGTH);
 
-	rc = nand_read(nand_info[0], (loff_t)CONFIG_SYS_FMAN_FW_ADDR,
+	rc = nand_read(get_nand_dev_by_index(0),
+		       (loff_t)CONFIG_SYS_FMAN_FW_ADDR,
 		       &fw_length, (u_char *)addr);
 	if (rc == -EUCLEAN) {
 		printf("NAND read of FMAN firmware at offset 0x%x failed %d\n",
diff --git a/drivers/net/phy/cortina.c b/drivers/net/phy/cortina.c
index fd130d5..e0e9ed9 100644
--- a/drivers/net/phy/cortina.c
+++ b/drivers/net/phy/cortina.c
@@ -139,7 +139,8 @@
 	size_t fw_length = CONFIG_CORTINA_FW_LENGTH;
 
 	addr = malloc(CONFIG_CORTINA_FW_LENGTH);
-	ret = nand_read(nand_info[0], (loff_t)CONFIG_CORTINA_FW_ADDR,
+	ret = nand_read(get_nand_dev_by_index(0),
+			(loff_t)CONFIG_CORTINA_FW_ADDR,
 			&fw_length, (u_char *)addr);
 	if (ret == -EUCLEAN) {
 		printf("NAND read of Cortina firmware at 0x%x failed %d\n",
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index b911233..d360a17 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -62,4 +62,11 @@
 	  The watchdog timer is stopped when initialized.
 	  It performs full SoC reset.
 
+config WDT_ORION
+	bool "Orion watchdog timer support"
+	depends on WDT
+	help
+	   Select this to enable Orion watchdog timer, which can be found on some
+	   Marvell Armada chips.
+
 endmenu
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 4b19e4c..3230cbb 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -20,3 +20,4 @@
 obj-$(CONFIG_WDT_ASPEED) += ast_wdt.o
 obj-$(CONFIG_WDT_BCM6345) += bcm6345_wdt.o
 obj-$(CONFIG_BCM2835_WDT)       += bcm2835_wdt.o
+obj-$(CONFIG_WDT_ORION) += orion_wdt.o
diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c
new file mode 100644
index 0000000..a0df02d
--- /dev/null
+++ b/drivers/watchdog/orion_wdt.c
@@ -0,0 +1,177 @@
+/*
+ * drivers/watchdog/orion_wdt.c
+ *
+ * Watchdog driver for Orion/Kirkwood processors
+ *
+ * Authors:	Tomas Hlavacek <tmshlvck@gmail.com>
+ * 		Sylver Bruneau <sylver.bruneau@googlemail.com>
+ * 		Marek Behun <marek.behun@nic.cz>
+ *
+ * This file is licensed under  the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <wdt.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct orion_wdt_priv {
+	void __iomem *reg;
+	int wdt_counter_offset;
+	void __iomem *rstout;
+	void __iomem *rstout_mask;
+	u32 timeout;
+};
+
+#define RSTOUT_ENABLE_BIT		BIT(8)
+#define RSTOUT_MASK_BIT			BIT(10)
+#define WDT_ENABLE_BIT			BIT(8)
+
+#define TIMER_CTRL			0x0000
+#define TIMER_A370_STATUS		0x04
+
+#define WDT_AXP_FIXED_ENABLE_BIT	BIT(10)
+#define WDT_A370_EXPIRED		BIT(31)
+
+static int orion_wdt_reset(struct udevice *dev)
+{
+	struct orion_wdt_priv *priv = dev_get_priv(dev);
+
+	/* Reload watchdog duration */
+	writel(priv->timeout, priv->reg + priv->wdt_counter_offset);
+
+	return 0;
+}
+
+static int orion_wdt_start(struct udevice *dev, u64 timeout, ulong flags)
+{
+	struct orion_wdt_priv *priv = dev_get_priv(dev);
+	u32 reg;
+
+	priv->timeout = (u32) timeout;
+
+	/* Enable the fixed watchdog clock input */
+	reg = readl(priv->reg + TIMER_CTRL);
+	reg |= WDT_AXP_FIXED_ENABLE_BIT;
+	writel(reg, priv->reg + TIMER_CTRL);
+
+	/* Set watchdog duration */
+	writel(priv->timeout, priv->reg + priv->wdt_counter_offset);
+
+	/* Clear the watchdog expiration bit */
+	reg = readl(priv->reg + TIMER_A370_STATUS);
+	reg &= ~WDT_A370_EXPIRED;
+	writel(reg, priv->reg + TIMER_A370_STATUS);
+
+	/* Enable watchdog timer */
+	reg = readl(priv->reg + TIMER_CTRL);
+	reg |= WDT_ENABLE_BIT;
+	writel(reg, priv->reg + TIMER_CTRL);
+
+	/* Enable reset on watchdog */
+	reg = readl(priv->rstout);
+	reg |= RSTOUT_ENABLE_BIT;
+	writel(reg, priv->rstout);
+
+	reg = readl(priv->rstout_mask);
+	reg &= ~RSTOUT_MASK_BIT;
+	writel(reg, priv->rstout_mask);
+
+	return 0;
+}
+
+static int orion_wdt_stop(struct udevice *dev)
+{
+	struct orion_wdt_priv *priv = dev_get_priv(dev);
+	u32 reg;
+
+	/* Disable reset on watchdog */
+	reg = readl(priv->rstout_mask);
+	reg |= RSTOUT_MASK_BIT;
+	writel(reg, priv->rstout_mask);
+
+	reg = readl(priv->rstout);
+	reg &= ~RSTOUT_ENABLE_BIT;
+	writel(reg, priv->rstout);
+
+	/* Disable watchdog timer */
+	reg = readl(priv->reg + TIMER_CTRL);
+	reg &= ~WDT_ENABLE_BIT;
+	writel(reg, priv->reg + TIMER_CTRL);
+
+	return 0;
+}
+
+static inline bool save_reg_from_ofdata(struct udevice *dev, int index,
+					void __iomem **reg, int *offset)
+{
+	fdt_addr_t addr;
+	fdt_size_t off;
+
+	addr = fdtdec_get_addr_size_auto_noparent(
+		gd->fdt_blob, dev_of_offset(dev), "reg", index, &off, true);
+
+	if (addr == FDT_ADDR_T_NONE)
+		return false;
+
+	*reg = (void __iomem *) addr;
+	if (offset)
+		*offset = off;
+
+	return true;
+}
+
+static int orion_wdt_ofdata_to_platdata(struct udevice *dev)
+{
+	struct orion_wdt_priv *priv = dev_get_priv(dev);
+
+	if (!save_reg_from_ofdata(dev, 0, &priv->reg,
+				  &priv->wdt_counter_offset))
+		goto err;
+
+	if (!save_reg_from_ofdata(dev, 1, &priv->rstout, NULL))
+		goto err;
+
+	if (!save_reg_from_ofdata(dev, 2, &priv->rstout_mask, NULL))
+		goto err;
+
+	return 0;
+err:
+	debug("%s: Could not determine Orion wdt IO addresses\n", __func__);
+	return -ENXIO;
+}
+
+static int orion_wdt_probe(struct udevice *dev)
+{
+	debug("%s: Probing wdt%u\n", __func__, dev->seq);
+	orion_wdt_stop(dev);
+
+	return 0;
+}
+
+static const struct wdt_ops orion_wdt_ops = {
+	.start = orion_wdt_start,
+	.reset = orion_wdt_reset,
+	.stop = orion_wdt_stop,
+};
+
+static const struct udevice_id orion_wdt_ids[] = {
+	{ .compatible = "marvell,armada-380-wdt" },
+	{}
+};
+
+U_BOOT_DRIVER(orion_wdt) = {
+	.name = "orion_wdt",
+	.id = UCLASS_WDT,
+	.of_match = orion_wdt_ids,
+	.probe = orion_wdt_probe,
+	.priv_auto_alloc_size = sizeof(struct orion_wdt_priv),
+	.ofdata_to_platdata = orion_wdt_ofdata_to_platdata,
+	.ops = &orion_wdt_ops,
+};
diff --git a/fs/jffs2/jffs2_1pass.c b/fs/jffs2/jffs2_1pass.c
index ed60c5b..4c6dfbf 100644
--- a/fs/jffs2/jffs2_1pass.c
+++ b/fs/jffs2/jffs2_1pass.c
@@ -175,10 +175,15 @@
 static int read_nand_cached(u32 off, u32 size, u_char *buf)
 {
 	struct mtdids *id = current_part->dev->id;
+	struct mtd_info *mtd;
 	u32 bytes_read = 0;
 	size_t retlen;
 	int cpy_bytes;
 
+	mtd = get_nand_dev_by_index(id->num);
+	if (!mtd)
+		return -1;
+
 	while (bytes_read < size) {
 		if ((off + bytes_read < nand_cache_off) ||
 		    (off + bytes_read >= nand_cache_off+NAND_CACHE_SIZE)) {
@@ -195,8 +200,8 @@
 			}
 
 			retlen = NAND_CACHE_SIZE;
-			if (nand_read(nand_info[id->num], nand_cache_off,
-						&retlen, nand_cache) != 0 ||
+			if (nand_read(mtd, nand_cache_off,
+				      &retlen, nand_cache) != 0 ||
 					retlen != NAND_CACHE_SIZE) {
 				printf("read_nand_cached: error reading nand off %#x size %d bytes\n",
 						nand_cache_off, NAND_CACHE_SIZE);
diff --git a/fs/jffs2/jffs2_nand_1pass.c b/fs/jffs2/jffs2_nand_1pass.c
index d94c48f..1d63fc9 100644
--- a/fs/jffs2/jffs2_nand_1pass.c
+++ b/fs/jffs2/jffs2_nand_1pass.c
@@ -796,7 +796,11 @@
 	u32 counterN = 0;
 
 	struct mtdids *id = part->dev->id;
-	mtd = nand_info[id->num];
+	mtd = get_nand_dev_by_index(id->num);
+	if (!mtd) {
+		error("\nno NAND devices available\n");
+		return 0;
+	}
 
 	/* if we are building a list we need to refresh the cache. */
 	jffs_init_1pass_list(part);
diff --git a/fs/yaffs2/yaffs_uboot_glue.c b/fs/yaffs2/yaffs_uboot_glue.c
index f663081..bd66d316 100644
--- a/fs/yaffs2/yaffs_uboot_glue.c
+++ b/fs/yaffs2/yaffs_uboot_glue.c
@@ -166,11 +166,15 @@
 	char *mp = NULL;
 	struct nand_chip *chip;
 
+	mtd = get_nand_dev_by_index(flash_dev);
+	if (!mtd) {
+		error("\nno NAND devices available\n");
+		return;
+	}
+
 	dev = calloc(1, sizeof(*dev));
 	mp = strdup(_mp);
 
-	mtd = nand_info[flash_dev];
-
 	if (!dev || !mp) {
 		/* Alloc error */
 		printf("Failed to allocate memory\n");
diff --git a/include/atsha204a-i2c.h b/include/atsha204a-i2c.h
new file mode 100644
index 0000000..344fd8a
--- /dev/null
+++ b/include/atsha204a-i2c.h
@@ -0,0 +1,69 @@
+/*
+ * I2C Driver for Atmel ATSHA204 over I2C
+ *
+ * Copyright (C) 2014 Josh Datko, Cryptotronix, jbd@cryptotronix.com
+ * 		 2016 Tomas Hlavacek, CZ.NIC, tmshlvck@gmail.com
+ * 		 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef _ATSHA204_I2C_H_
+#define _ATSHA204_I2C_H_
+
+enum atsha204a_zone
+{
+	ATSHA204A_ZONE_CONFIG	= 0,
+	ATSHA204A_ZONE_OTP	= 1,
+	ATSHA204A_ZONE_DATA	= 2,
+};
+
+enum atsha204a_status
+{
+	ATSHA204A_STATUS_SUCCESS	= 0x00,
+	ATSHA204A_STATUS_MISCOMPARE	= 0x01,
+	ATSHA204A_STATUS_PARSE_ERROR	= 0x03,
+	ATSHA204A_STATUS_EXEC_ERROR	= 0x0F,
+	ATSHA204A_STATUS_AFTER_WAKE	= 0x11,
+	ATSHA204A_STATUS_CRC_ERROR	= 0xFF,
+};
+
+enum atsha204a_func
+{
+	ATSHA204A_FUNC_RESET	= 0x00,
+	ATSHA204A_FUNC_SLEEP	= 0x01,
+	ATSHA204A_FUNC_IDLE	= 0x02,
+	ATSHA204A_FUNC_COMMAND	= 0x03,
+};
+
+enum atsha204a_cmd
+{
+	ATSHA204A_CMD_READ	= 0x02,
+	ATSHA204A_CMD_RANDOM	= 0x1B,
+};
+
+struct atsha204a_resp
+{
+	u8 length;
+	u8 code;
+	u8 data[82];
+} __attribute__ ((packed));
+
+struct atsha204a_req
+{
+	u8 function;
+	u8 length;
+	u8 command;
+	u8 param1;
+	u16 param2;
+	u8 data[78];
+} __attribute__ ((packed));
+
+int atsha204a_wakeup(struct udevice *);
+int atsha204a_idle(struct udevice *);
+int atsha204a_sleep(struct udevice *);
+int atsha204a_read(struct udevice *, enum atsha204a_zone, bool, u16, u8 *);
+int atsha204a_get_random(struct udevice *, u8 *, size_t);
+
+#endif /* _ATSHA204_I2C_H_ */
diff --git a/include/configs/am335x_evm.h b/include/configs/am335x_evm.h
index 0c6d288..b97f525 100644
--- a/include/configs/am335x_evm.h
+++ b/include/configs/am335x_evm.h
@@ -270,11 +270,7 @@
 
 #ifndef CONFIG_SPL_USBETH_SUPPORT
 /* Fastboot */
-#define CONFIG_USB_FUNCTION_FASTBOOT
-#define CONFIG_CMD_FASTBOOT
 #define CONFIG_ANDROID_BOOT_IMAGE
-#define CONFIG_FASTBOOT_BUF_ADDR	CONFIG_SYS_LOAD_ADDR
-#define CONFIG_FASTBOOT_BUF_SIZE	0x07000000
 
 #define CONFIG_FASTBOOT_FLASH_MMC_DEV   1
 #endif
diff --git a/include/configs/turris_omnia.h b/include/configs/turris_omnia.h
new file mode 100644
index 0000000..4ad603d
--- /dev/null
+++ b/include/configs/turris_omnia.h
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2017 Marek Behun <marek.behun@nic.cz>
+ * Copyright (C) 2016 Tomas Hlavacek <tomas.hlavacek@nic.cz>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _CONFIG_TURRIS_OMNIA_H
+#define _CONFIG_TURRIS_OMNIA_H
+
+/*
+ * High Level Configuration Options (easy to change)
+ */
+
+#define CONFIG_MISC_INIT_R
+#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_CMD_PCI
+
+/* I2C support */
+#define CONFIG_DM_I2C
+#define CONFIG_I2C_MUX
+#define CONFIG_I2C_MUX_PCA954x
+#define CONFIG_SPL_I2C_MUX
+#define CONFIG_SYS_I2C_MVTWSI
+
+/* Watchdog support */
+#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_WDT_ORION)
+# define CONFIG_WATCHDOG
+#endif
+
+/* 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
+#define CONFIG_SPI_FLASH_SPANSION
+
+/*
+ * SDIO/MMC Card Configuration
+ */
+#define CONFIG_SYS_MMC_BASE		MVEBU_SDIO_BASE
+
+/*
+ * SATA/SCSI/AHCI configuration
+ */
+#define CONFIG_LIBATA
+#define CONFIG_SCSI_AHCI
+#define CONFIG_SCSI_AHCI_PLAT
+#define CONFIG_SYS_SCSI_MAX_SCSI_ID	2
+#define CONFIG_SYS_SCSI_MAX_LUN		1
+#define CONFIG_SYS_SCSI_MAX_DEVICE	(CONFIG_SYS_SCSI_MAX_SCSI_ID * \
+					 CONFIG_SYS_SCSI_MAX_LUN)
+
+/* Additional FS support/configuration */
+#define CONFIG_SUPPORT_VFAT
+
+/* USB/EHCI configuration */
+#define CONFIG_EHCI_IS_TDI
+
+/* Environment in SPI NOR flash */
+#define CONFIG_ENV_IS_IN_SPI_FLASH
+#define CONFIG_ENV_OFFSET		(3*(1 << 18)) /* 768KiB in */
+#define CONFIG_ENV_SIZE			(64 << 10) /* 64KiB */
+#define CONFIG_ENV_SECT_SIZE		(256 << 10) /* 256KiB sectors */
+
+#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_MVEBU
+#define CONFIG_PCI_SCAN_SHOW
+#endif
+
+#define CONFIG_SYS_ALT_MEMTEST
+
+/* Keep device tree and initrd in lower memory so the kernel can access them */
+#define RELOCATION_LIMITS_ENV_SETTINGS	\
+	"fdt_high=0x10000000\0"		\
+	"initrd_high=0x10000000\0"
+
+/* 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_DRIVERS_MISC_SUPPORT
+
+#ifdef CONFIG_TURRIS_OMNIA_SPL_BOOT_DEVICE_SPI
+/* SPL related SPI defines */
+# define CONFIG_SPL_SPI_LOAD
+# define CONFIG_SYS_SPI_U_BOOT_OFFS	0x24000
+# define CONFIG_SYS_U_BOOT_OFFS		CONFIG_SYS_SPI_U_BOOT_OFFS
+#endif
+
+#ifdef CONFIG_TURRIS_OMNIA_SPL_BOOT_DEVICE_MMC
+/* SPL related MMC defines */
+# define CONFIG_SYS_MMC_U_BOOT_OFFS		(160 << 10)
+# define CONFIG_SYS_U_BOOT_OFFS			CONFIG_SYS_MMC_U_BOOT_OFFS
+# 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"
+
+/* Include the common distro boot environment */
+#ifndef CONFIG_SPL_BUILD
+#include <config_distro_defaults.h>
+
+#ifdef CONFIG_MMC
+#define BOOT_TARGET_DEVICES_MMC(func) func(MMC, mmc, 0)
+#else
+#define BOOT_TARGET_DEVICES_MMC(func)
+#endif
+
+#ifdef CONFIG_USB_STORAGE
+#define BOOT_TARGET_DEVICES_USB(func) func(USB, usb, 0)
+#else
+#define BOOT_TARGET_DEVICES_USB(func)
+#endif
+
+#define BOOT_TARGET_DEVICES(func) \
+	BOOT_TARGET_DEVICES_MMC(func) \
+	BOOT_TARGET_DEVICES_USB(func) \
+	func(PXE, pxe, na) \
+	func(DHCP, dhcp, na)
+
+#define KERNEL_ADDR_R	__stringify(0x1000000)
+#define FDT_ADDR_R	__stringify(0x2000000)
+#define RAMDISK_ADDR_R	__stringify(0x2200000)
+#define SCRIPT_ADDR_R	__stringify(0x1800000)
+#define PXEFILE_ADDR_R	__stringify(0x1900000)
+
+#define LOAD_ADDRESS_ENV_SETTINGS \
+	"kernel_addr_r=" KERNEL_ADDR_R "\0" \
+	"fdt_addr_r=" FDT_ADDR_R "\0" \
+	"ramdisk_addr_r=" RAMDISK_ADDR_R "\0" \
+	"scriptaddr=" SCRIPT_ADDR_R "\0" \
+	"pxefile_addr_r=" PXEFILE_ADDR_R "\0"
+
+#include <config_distro_bootcmd.h>
+
+#define CONFIG_EXTRA_ENV_SETTINGS \
+	RELOCATION_LIMITS_ENV_SETTINGS \
+	LOAD_ADDRESS_ENV_SETTINGS \
+	"fdtfile=" CONFIG_DEFAULT_DEVICE_TREE ".dtb\0" \
+	"console=ttyS0,115200\0" \
+	BOOTENV
+
+#endif /* CONFIG_SPL_BUILD */
+
+#endif /* _CONFIG_TURRIS_OMNIA_H */
diff --git a/include/nand.h b/include/nand.h
index bc5dd81..c1c1d8c 100644
--- a/include/nand.h
+++ b/include/nand.h
@@ -44,7 +44,6 @@
 #endif
 
 extern int nand_curr_device;
-extern struct mtd_info *nand_info[];
 
 static inline int nand_read(struct mtd_info *info, loff_t ofs, size_t *len,
 			    u_char *buf)
@@ -145,4 +144,13 @@
 /* platform specific init functions */
 void sunxi_nand_init(void);
 
+/*
+ * get_nand_dev_by_index - Get the nand info based in index.
+ *
+ * @dev - index to the nand device.
+ *
+ * returns pointer to the nand device info structure or NULL on failure.
+ */
+struct mtd_info *get_nand_dev_by_index(int dev);
+
 #endif /* _NAND_H_ */
diff --git a/tools/kwbimage.c b/tools/kwbimage.c
index 5830549..ccecf87 100644
--- a/tools/kwbimage.c
+++ b/tools/kwbimage.c
@@ -290,6 +290,33 @@
 	return csum;
 }
 
+size_t kwbimage_header_size(unsigned char *ptr)
+{
+	if (image_version((void *)ptr) == 0)
+		return sizeof(struct main_hdr_v0);
+	else
+		return KWBHEADER_V1_SIZE((struct main_hdr_v1 *)ptr);
+}
+
+/*
+ * Verify checksum over a complete header that includes the checksum field.
+ * Return 1 when OK, otherwise 0.
+ */
+static int main_hdr_checksum_ok(void *hdr)
+{
+	/* Offsets of checksum in v0 and v1 headers are the same */
+	struct main_hdr_v0 *main_hdr = (struct main_hdr_v0 *)hdr;
+	uint8_t checksum;
+
+	checksum = image_checksum8(hdr, kwbimage_header_size(hdr));
+	/* Calculated checksum includes the header checksum field. Compensate
+	 * for that.
+	 */
+	checksum -= main_hdr->checksum;
+
+	return checksum == main_hdr->checksum;
+}
+
 static uint32_t image_checksum32(void *start, uint32_t len)
 {
 	uint32_t csum = 0;
@@ -1587,14 +1614,9 @@
 static int kwbimage_verify_header(unsigned char *ptr, int image_size,
 				  struct image_tool_params *params)
 {
-	struct main_hdr_v0 *main_hdr;
 	uint8_t checksum;
 
-	main_hdr = (struct main_hdr_v0 *)ptr;
-	checksum = image_checksum8(ptr,
-				   sizeof(struct main_hdr_v0)
-				   - sizeof(uint8_t));
-	if (checksum != main_hdr->checksum)
+	if (!main_hdr_checksum_ok(ptr))
 		return -FDT_ERR_BADSTRUCTURE;
 
 	/* Only version 0 extended header has checksum */
diff --git a/tools/kwbimage.h b/tools/kwbimage.h
index 20f4d0d..2160c8f 100644
--- a/tools/kwbimage.h
+++ b/tools/kwbimage.h
@@ -34,20 +34,20 @@
 
 /* Structure of the main header, version 0 (Kirkwood, Dove) */
 struct main_hdr_v0 {
-	uint8_t  blockid;		/*0     */
-	uint8_t  nandeccmode;		/*1     */
-	uint16_t nandpagesize;		/*2-3   */
-	uint32_t blocksize;		/*4-7   */
-	uint32_t rsvd1;			/*8-11  */
-	uint32_t srcaddr;		/*12-15 */
-	uint32_t destaddr;		/*16-19 */
-	uint32_t execaddr;		/*20-23 */
-	uint8_t  satapiomode;		/*24    */
-	uint8_t  rsvd3;			/*25    */
-	uint16_t ddrinitdelay;		/*26-27 */
-	uint16_t rsvd2;			/*28-29 */
-	uint8_t  ext;			/*30    */
-	uint8_t  checksum;		/*31    */
+	uint8_t  blockid;		/* 0x0       */
+	uint8_t  nandeccmode;		/* 0x1       */
+	uint16_t nandpagesize;		/* 0x2-0x3   */
+	uint32_t blocksize;		/* 0x4-0x7   */
+	uint32_t rsvd1;			/* 0x8-0xB   */
+	uint32_t srcaddr;		/* 0xC-0xF   */
+	uint32_t destaddr;		/* 0x10-0x13 */
+	uint32_t execaddr;		/* 0x14-0x17 */
+	uint8_t  satapiomode;		/* 0x18      */
+	uint8_t  rsvd3;			/* 0x19      */
+	uint16_t ddrinitdelay;		/* 0x1A-0x1B */
+	uint16_t rsvd2;			/* 0x1C-0x1D */
+	uint8_t  ext;			/* 0x1E      */
+	uint8_t  checksum;		/* 0x1F      */
 };
 
 struct ext_hdr_v0_reg {
@@ -70,25 +70,25 @@
 	struct ext_hdr_v0	kwb_exthdr;
 };
 
-/* Structure of the main header, version 1 (Armada 370, Armada XP) */
+/* Structure of the main header, version 1 (Armada 370/38x/XP) */
 struct main_hdr_v1 {
-	uint8_t  blockid;               /* 0 */
-	uint8_t  flags;                 /* 1 */
-	uint16_t reserved2;             /* 2-3 */
-	uint32_t blocksize;             /* 4-7 */
-	uint8_t  version;               /* 8 */
-	uint8_t  headersz_msb;          /* 9 */
-	uint16_t headersz_lsb;          /* A-B */
-	uint32_t srcaddr;               /* C-F */
-	uint32_t destaddr;              /* 10-13 */
-	uint32_t execaddr;              /* 14-17 */
-	uint8_t  options;               /* 18 */
-	uint8_t  nandblocksize;         /* 19 */
-	uint8_t  nandbadblklocation;    /* 1A */
-	uint8_t  reserved4;             /* 1B */
-	uint16_t reserved5;             /* 1C-1D */
-	uint8_t  ext;                   /* 1E */
-	uint8_t  checksum;              /* 1F */
+	uint8_t  blockid;               /* 0x0       */
+	uint8_t  flags;                 /* 0x1       */
+	uint16_t reserved2;             /* 0x2-0x3   */
+	uint32_t blocksize;             /* 0x4-0x7   */
+	uint8_t  version;               /* 0x8       */
+	uint8_t  headersz_msb;          /* 0x9       */
+	uint16_t headersz_lsb;          /* 0xA-0xB   */
+	uint32_t srcaddr;               /* 0xC-0xF   */
+	uint32_t destaddr;              /* 0x10-0x13 */
+	uint32_t execaddr;              /* 0x14-0x17 */
+	uint8_t  options;               /* 0x18      */
+	uint8_t  nandblocksize;         /* 0x19      */
+	uint8_t  nandbadblklocation;    /* 0x1A      */
+	uint8_t  reserved4;             /* 0x1B      */
+	uint16_t reserved5;             /* 0x1C-0x1D */
+	uint8_t  ext;                   /* 0x1E      */
+	uint8_t  checksum;              /* 0x1F      */
 };
 
 /*