Merge branch 'master' of git://git.denx.de/u-boot-usb

Modified:
	configs/ls1012afrdm_qspi_defconfig
	configs/ls1012aqds_qspi_defconfig
	configs/ls1012ardb_qspi_defconfig
	include/configs/ls1012afrdm.h
	include/configs/ls1012aqds.h
	include/configs/ls1012ardb.h

Signed-off-by: Tom Rini <trini@konsulko.com>
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 77eab66..72b0aa7 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -710,6 +710,33 @@
 	  Support for HiKey 96boards platform. It features a HI6220
 	  SoC, with 8xA53 CPU, mali450 gpu, and 1GB RAM.
 
+config TARGET_LS1012AQDS
+	bool "Support ls1012aqds"
+	select ARM64
+	help
+	  Support for Freescale LS1012AQDS platform.
+	  The LS1012A Development System (QDS) is a high-performance
+	  development platform that supports the QorIQ LS1012A
+	  Layerscape Architecture processor.
+
+config TARGET_LS1012ARDB
+	bool "Support ls1012ardb"
+	select ARM64
+	help
+	  Support for Freescale LS1012ARDB platform.
+	  The LS1012A Reference design board (RDB) is a high-performance
+	  development platform that supports the QorIQ LS1012A
+	  Layerscape Architecture processor.
+
+config TARGET_LS1012AFRDM
+	bool "Support ls1012afrdm"
+	select ARM64
+	help
+	  Support for Freescale LS1012AFRDM platform.
+	  The LS1012A Freedom  board (FRDM) is a high-performance
+	  development platform that supports the QorIQ LS1012A
+	  Layerscape Architecture processor.
+
 config TARGET_LS1021AQDS
 	bool "Support ls1021aqds"
 	select CPU_V7
@@ -867,6 +894,9 @@
 source "board/freescale/ls1043aqds/Kconfig"
 source "board/freescale/ls1021atwr/Kconfig"
 source "board/freescale/ls1043ardb/Kconfig"
+source "board/freescale/ls1012aqds/Kconfig"
+source "board/freescale/ls1012ardb/Kconfig"
+source "board/freescale/ls1012afrdm/Kconfig"
 source "board/freescale/mx23evk/Kconfig"
 source "board/freescale/mx25pdk/Kconfig"
 source "board/freescale/mx28evk/Kconfig"
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/Makefile b/arch/arm/cpu/armv8/fsl-layerscape/Makefile
index 5f86ef9..eb2cbc3 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/Makefile
+++ b/arch/arm/cpu/armv8/fsl-layerscape/Makefile
@@ -28,3 +28,7 @@
 ifneq ($(CONFIG_LS1043A),)
 obj-$(CONFIG_SYS_HAS_SERDES) += ls1043a_serdes.o
 endif
+
+ifneq ($(CONFIG_LS1012A),)
+obj-$(CONFIG_SYS_HAS_SERDES) += ls1012a_serdes.o
+endif
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/README.lsch2 b/arch/arm/cpu/armv8/fsl-layerscape/doc/README.lsch2
similarity index 100%
rename from arch/arm/cpu/armv8/fsl-layerscape/README.lsch2
rename to arch/arm/cpu/armv8/fsl-layerscape/doc/README.lsch2
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/README.lsch3 b/arch/arm/cpu/armv8/fsl-layerscape/doc/README.lsch3
similarity index 100%
rename from arch/arm/cpu/armv8/fsl-layerscape/README.lsch3
rename to arch/arm/cpu/armv8/fsl-layerscape/doc/README.lsch3
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/doc/README.soc b/arch/arm/cpu/armv8/fsl-layerscape/doc/README.soc
new file mode 100644
index 0000000..8eee016
--- /dev/null
+++ b/arch/arm/cpu/armv8/fsl-layerscape/doc/README.soc
@@ -0,0 +1,129 @@
+SoC overview
+
+	1. LS1043A
+	2. LS2080A
+	3. LS1012A
+
+LS1043A
+---------
+The LS1043A integrated multicore processor combines four ARM Cortex-A53
+processor cores with datapath acceleration optimized for L2/3 packet
+processing, single pass security offload and robust traffic management
+and quality of service.
+
+The LS1043A SoC includes the following function and features:
+ - Four 64-bit ARM Cortex-A53 CPUs
+ - 1 MB unified L2 Cache
+ - One 32-bit DDR3L/DDR4 SDRAM memory controllers with ECC and interleaving
+   support
+ - Data Path Acceleration Architecture (DPAA) incorporating acceleration the
+   the following functions:
+   - Packet parsing, classification, and distribution (FMan)
+   - Queue management for scheduling, packet sequencing, and congestion
+     management (QMan)
+   - Hardware buffer management for buffer allocation and de-allocation (BMan)
+   - Cryptography acceleration (SEC)
+ - Ethernet interfaces by FMan
+   - Up to 1 x XFI supporting 10G interface
+   - Up to 1 x QSGMII
+   - Up to 4 x SGMII supporting 1000Mbps
+   - Up to 2 x SGMII supporting 2500Mbps
+   - Up to 2 x RGMII supporting 1000Mbps
+ - High-speed peripheral interfaces
+   - Three PCIe 2.0 controllers, one supporting x4 operation
+   - One serial ATA (SATA 3.0) controllers
+ - Additional peripheral interfaces
+   - Three high-speed USB 3.0 controllers with integrated PHY
+   - Enhanced secure digital host controller (eSDXC/eMMC)
+   - Quad Serial Peripheral Interface (QSPI) Controller
+   - Serial peripheral interface (SPI) controller
+   - Four I2C controllers
+   - Two DUARTs
+   - Integrated flash controller supporting NAND and NOR flash
+ - QorIQ platform's trust architecture 2.1
+
+LS2080A
+--------
+The LS2080A integrated multicore processor combines eight ARM Cortex-A57
+processor cores with high-performance data path acceleration logic and network
+and peripheral bus interfaces required for networking, telecom/datacom,
+wireless infrastructure, and mil/aerospace applications.
+
+The LS2080A SoC includes the following function and features:
+
+ - Eight 64-bit ARM Cortex-A57 CPUs
+ - 1 MB platform cache with ECC
+ - Two 64-bit DDR4 SDRAM memory controllers with ECC and interleaving support
+ - One secondary 32-bit DDR4 SDRAM memory controller, intended for use by
+  the AIOP
+ - Data path acceleration architecture (DPAA2) incorporating acceleration for
+ the following functions:
+   - Packet parsing, classification, and distribution (WRIOP)
+   - Queue and Hardware buffer management for scheduling, packet sequencing, and
+     congestion management, buffer allocation and de-allocation (QBMan)
+   - Cryptography acceleration (SEC) at up to 10 Gbps
+   - RegEx pattern matching acceleration (PME) at up to 10 Gbps
+   - Decompression/compression acceleration (DCE) at up to 20 Gbps
+   - Accelerated I/O processing (AIOP) at up to 20 Gbps
+   - QDMA engine
+ - 16 SerDes lanes at up to 10.3125 GHz
+ - Ethernet interfaces
+   - Up to eight 10 Gbps Ethernet MACs
+   - Up to eight 1 / 2.5 Gbps Ethernet MACs
+ - High-speed peripheral interfaces
+   - Four PCIe 3.0 controllers, one supporting SR-IOV
+ - Additional peripheral interfaces
+   - Two serial ATA (SATA 3.0) controllers
+   - Two high-speed USB 3.0 controllers with integrated PHY
+   - Enhanced secure digital host controller (eSDXC/eMMC)
+   - Serial peripheral interface (SPI) controller
+   - Quad Serial Peripheral Interface (QSPI) Controller
+   - Four I2C controllers
+   - Two DUARTs
+   - Integrated flash controller (IFC 2.0) supporting NAND and NOR flash
+ - Support for hardware virtualization and partitioning enforcement
+ - QorIQ platform's trust architecture 3.0
+ - Service processor (SP) provides pre-boot initialization and secure-boot
+  capabilities
+
+LS1012A
+--------
+The LS1012A features an advanced 64-bit ARM v8 Cortex-
+A53 processor, with 32 KB of parity protected L1-I cache,
+32 KB of ECC protected L1-D cache, as well as 256 KB of
+ECC protected L2 cache.
+
+The LS1012A SoC includes the following function and features:
+ - One 64-bit ARM v8 Cortex-A53 core with the following capabilities:
+ - ARM v8 cryptography extensions
+ - One 16-bit DDR3L SDRAM memory controller, Up to 1.0 GT/s, Supports
+    16-/8-bit operation (no ECC support)
+ - ARM core-link CCI-400 cache coherent interconnect
+ - Packet Forwarding Engine (PFE)
+ - Cryptography acceleration (SEC)
+ - Ethernet interfaces supported by PFE:
+ - One Configurable x3 SerDes:
+    Two Serdes PLLs supported for usage by any SerDes data lane
+    Support for up to 6 GBaud operation
+ - High-speed peripheral interfaces:
+     - One PCI Express Gen2 controller, supporting x1 operation
+     - One serial ATA (SATA Gen 3.0) controller
+     - One USB 3.0/2.0 controller with integrated PHY
+     - One USB 2.0 controller with ULPI interface. .
+ - Additional peripheral interfaces:
+    - One quad serial peripheral interface (QuadSPI) controller
+    - One serial peripheral interface (SPI) controller
+    - Two enhanced secure digital host controllers
+    - Two I2C controllers
+    - One 16550 compliant DUART (two UART interfaces)
+    - Two general purpose IOs (GPIO)
+    - Two FlexTimers
+    - Five synchronous audio interfaces (SAI)
+    - Pre-boot loader (PBL) provides pre-boot initialization and RCW loading
+    - Single-source clocking solution enabling generation of core, platform,
+    DDR, SerDes, and USB clocks from a single external crystal and internal
+    crystaloscillator
+    - Thermal monitor unit (TMU) with +/- 3C accuracy
+    - Two WatchDog timers
+    - ARM generic timer
+ - QorIQ platform's trust architecture 2.1
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch2_speed.c b/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch2_speed.c
index 453a93d..3a77b21 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch2_speed.c
+++ b/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch2_speed.c
@@ -25,7 +25,10 @@
 	struct fsl_ifc ifc_regs = {(void *)CONFIG_SYS_IFC_ADDR, (void *)NULL};
 	u32 ccr;
 #endif
-#if defined(CONFIG_FSL_ESDHC) || defined(CONFIG_SYS_DPAA_FMAN)
+#if (defined(CONFIG_FSL_ESDHC) &&\
+	defined(CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK)) ||\
+	defined(CONFIG_SYS_DPAA_FMAN)
+
 	u32 rcw_tmp;
 #endif
 	struct ccsr_clk *clk = (void *)(CONFIG_SYS_FSL_CLK_ADDR);
@@ -56,12 +59,18 @@
 	sys_info->freq_ddrbus = sysclk;
 #endif
 
+#ifdef CONFIG_LS1012A
+	sys_info->freq_ddrbus *= (gur_in32(&gur->rcwsr[0]) >>
+			FSL_CHASSIS2_RCWSR0_SYS_PLL_RAT_SHIFT) &
+			FSL_CHASSIS2_RCWSR0_SYS_PLL_RAT_MASK;
+#else
 	sys_info->freq_systembus *= (gur_in32(&gur->rcwsr[0]) >>
 			FSL_CHASSIS2_RCWSR0_SYS_PLL_RAT_SHIFT) &
 			FSL_CHASSIS2_RCWSR0_SYS_PLL_RAT_MASK;
 	sys_info->freq_ddrbus *= (gur_in32(&gur->rcwsr[0]) >>
 			FSL_CHASSIS2_RCWSR0_MEM_PLL_RAT_SHIFT) &
 			FSL_CHASSIS2_RCWSR0_MEM_PLL_RAT_MASK;
+#endif
 
 	for (i = 0; i < CONFIG_SYS_FSL_NUM_CC_PLLS; i++) {
 		ratio[i] = (in_be32(&clk->pllcgsr[i].pllcngsr) >> 1) & 0xff;
@@ -80,6 +89,11 @@
 			freq_c_pll[cplx_pll] / core_cplx_pll_div[c_pll_sel];
 	}
 
+#ifdef CONFIG_LS1012A
+	sys_info->freq_systembus = sys_info->freq_ddrbus / 2;
+	sys_info->freq_ddrbus *= 2;
+#endif
+
 #define HWA_CGA_M1_CLK_SEL	0xe0000000
 #define HWA_CGA_M1_CLK_SHIFT	29
 #ifdef CONFIG_SYS_DPAA_FMAN
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S b/arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S
index 04831ca..5af6b73 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S
+++ b/arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S
@@ -94,11 +94,13 @@
 	bl	ccn504_set_qos
 #endif
 
+#ifdef SMMU_BASE
 	/* Set the SMMU page size in the sACR register */
 	ldr	x1, =SMMU_BASE
 	ldr	w0, [x1, #0x10]
 	orr	w0, w0, #1 << 16  /* set sACR.pagesize to indicate 64K page */
 	str	w0, [x1, #0x10]
+#endif
 
 	/* Initialize GIC Secure Bank Status */
 #if defined(CONFIG_GICV2) || defined(CONFIG_GICV3)
@@ -181,6 +183,7 @@
 	ret
 ENDPROC(lowlevel_init)
 
+#ifdef CONFIG_FSL_LSCH3
 hnf_pstate_poll:
 	/* x0 has the desired status, return 0 for success, 1 for timeout
 	 * clobber x1, x2, x3, x4, x6, x7
@@ -258,6 +261,7 @@
 	mov	lr, x29
 	ret
 ENDPROC(__asm_flush_l3_cache)
+#endif
 
 #ifdef CONFIG_MP
 	/* Keep literals not used by the secondary boot code outside it */
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/ls1012a_serdes.c b/arch/arm/cpu/armv8/fsl-layerscape/ls1012a_serdes.c
new file mode 100644
index 0000000..ff0903c
--- /dev/null
+++ b/arch/arm/cpu/armv8/fsl-layerscape/ls1012a_serdes.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/arch/fsl_serdes.h>
+#include <asm/arch/immap_lsch2.h>
+
+struct serdes_config {
+	u32 protocol;
+	u8 lanes[SRDS_MAX_LANES];
+};
+
+static struct serdes_config serdes1_cfg_tbl[] = {
+	{0x2208, {SGMII_2500_FM1_DTSEC1, SGMII_2500_FM1_DTSEC2, NONE, SATA1} },
+	{0x0008, {NONE, NONE, NONE, SATA1} },
+	{0x3508, {SGMII_FM1_DTSEC1, PCIE1, NONE, SATA1} },
+	{0x3305, {SGMII_FM1_DTSEC1, SGMII_FM1_DTSEC2, NONE, PCIE1} },
+	{0x2205, {SGMII_2500_FM1_DTSEC1, SGMII_2500_FM1_DTSEC2, NONE, PCIE1} },
+	{0x2305, {SGMII_2500_FM1_DTSEC1, SGMII_FM1_DTSEC2, NONE, PCIE1} },
+	{0x9508, {TX_CLK, PCIE1, NONE, SATA1} },
+	{0x3905, {SGMII_FM1_DTSEC1, TX_CLK, NONE, PCIE1} },
+	{0x9305, {TX_CLK, SGMII_FM1_DTSEC2, NONE, PCIE1} },
+	{}
+};
+
+static struct serdes_config *serdes_cfg_tbl[] = {
+	serdes1_cfg_tbl,
+};
+
+enum srds_prtcl serdes_get_prtcl(int serdes, int cfg, int lane)
+{
+	struct serdes_config *ptr;
+
+	if (serdes >= ARRAY_SIZE(serdes_cfg_tbl))
+		return 0;
+
+	ptr = serdes_cfg_tbl[serdes];
+	while (ptr->protocol) {
+		if (ptr->protocol == cfg)
+			return ptr->lanes[lane];
+		ptr++;
+	}
+
+	return 0;
+}
+
+int is_serdes_prtcl_valid(int serdes, u32 prtcl)
+{
+	int i;
+	struct serdes_config *ptr;
+
+	if (serdes >= ARRAY_SIZE(serdes_cfg_tbl))
+		return 0;
+
+	ptr = serdes_cfg_tbl[serdes];
+	while (ptr->protocol) {
+		if (ptr->protocol == prtcl)
+			break;
+		ptr++;
+	}
+
+	if (!ptr->protocol)
+		return 0;
+
+	for (i = 0; i < SRDS_MAX_LANES; i++) {
+		if (ptr->lanes[i] != NONE)
+			return 1;
+	}
+
+	return 0;
+}
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/soc.c b/arch/arm/cpu/armv8/fsl-layerscape/soc.c
index 0fb5c7f..dd633f3 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/soc.c
+++ b/arch/arm/cpu/armv8/fsl-layerscape/soc.c
@@ -12,8 +12,10 @@
 #include <asm/io.h>
 #include <asm/global_data.h>
 #include <asm/arch-fsl-layerscape/config.h>
+#ifdef CONFIG_SYS_FSL_DDR
 #include <fsl_ddr_sdram.h>
 #include <fsl_ddr.h>
+#endif
 #ifdef CONFIG_CHAIN_OF_TRUST
 #include <fsl_validate.h>
 #endif
@@ -224,7 +226,7 @@
 }
 #endif
 
-#elif defined(CONFIG_LS1043A)
+#elif defined(CONFIG_FSL_LSCH2)
 #ifdef CONFIG_SCSI_AHCI_PLAT
 int sata_init(void)
 {
diff --git a/arch/arm/cpu/armv8/zynqmp/cpu.c b/arch/arm/cpu/armv8/zynqmp/cpu.c
index 5dd3cd8..509f0aa 100644
--- a/arch/arm/cpu/armv8/zynqmp/cpu.c
+++ b/arch/arm/cpu/armv8/zynqmp/cpu.c
@@ -63,6 +63,11 @@
 };
 struct mm_region *mem_map = zynqmp_mem_map;
 
+u64 get_page_table_size(void)
+{
+	return 0x14000;
+}
+
 static unsigned int zynqmp_get_silicon_version_secure(void)
 {
 	u32 ver;
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index e76f56b..1814797 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -47,6 +47,7 @@
 	tegra124-jetson-tk1.dtb \
 	tegra124-nyan-big.dtb \
 	tegra124-venice2.dtb \
+	tegra186-p2771-0000.dtb \
 	tegra210-e2220-1170.dtb \
 	tegra210-p2371-0000.dtb \
 	tegra210-p2371-2180.dtb \
@@ -90,6 +91,7 @@
 	zynqmp-zcu102-revB.dtb			\
 	zynqmp-zc1751-xm015-dc1.dtb		\
 	zynqmp-zc1751-xm016-dc2.dtb		\
+	zynqmp-zc1751-xm018-dc4.dtb		\
 	zynqmp-zc1751-xm019-dc5.dtb
 dtb-$(CONFIG_AM33XX) += am335x-boneblack.dtb am335x-bone.dtb am335x-evm.dtb \
 	am335x-evmsk.dtb \
@@ -121,7 +123,10 @@
 	fsl-ls2080a-rdb.dtb
 dtb-$(CONFIG_FSL_LSCH2) += fsl-ls1043a-qds-duart.dtb \
 	fsl-ls1043a-qds-lpuart.dtb \
-	fsl-ls1043a-rdb.dtb
+	fsl-ls1043a-rdb.dtb \
+	fsl-ls1012a-qds.dtb \
+	fsl-ls1012a-rdb.dtb \
+	fsl-ls1012a-frdm.dtb
 
 dtb-$(CONFIG_ARCH_SNAPDRAGON) += dragonboard410c.dtb
 
diff --git a/arch/arm/dts/fsl-ls1012a-frdm.dts b/arch/arm/dts/fsl-ls1012a-frdm.dts
new file mode 100644
index 0000000..983e599
--- /dev/null
+++ b/arch/arm/dts/fsl-ls1012a-frdm.dts
@@ -0,0 +1,16 @@
+/*
+ * Device Tree file for Freescale Layerscape-1012A family SoC.
+ *
+ * Copyright 2016, Freescale Semiconductor
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/dts-v1/;
+#include "fsl-ls1012a-frdm.dtsi"
+
+/ {
+	chosen {
+		stdout-path = &duart0;
+	};
+};
diff --git a/arch/arm/dts/fsl-ls1012a-frdm.dtsi b/arch/arm/dts/fsl-ls1012a-frdm.dtsi
new file mode 100644
index 0000000..25dcdd2
--- /dev/null
+++ b/arch/arm/dts/fsl-ls1012a-frdm.dtsi
@@ -0,0 +1,37 @@
+/*
+ * Device Tree file for Freescale Layerscape-1012A family SoC.
+ *
+ * Copyright 2016, Freescale Semiconductor
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/include/ "fsl-ls1012a.dtsi"
+
+/ {
+	model = "LS1012A FREEDOM Board";
+	aliases {
+		spi0 = &qspi;
+	};
+};
+
+&qspi {
+	bus-num = <0>;
+	status = "okay";
+
+	qflash0: s25fl128s@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "spi-flash";
+		spi-max-frequency = <20000000>;
+		reg = <0>;
+	};
+};
+
+&i2c0 {
+	status = "okay";
+};
+
+&duart0 {
+	status = "okay";
+};
diff --git a/arch/arm/dts/fsl-ls1012a-qds.dts b/arch/arm/dts/fsl-ls1012a-qds.dts
new file mode 100644
index 0000000..76db36c
--- /dev/null
+++ b/arch/arm/dts/fsl-ls1012a-qds.dts
@@ -0,0 +1,14 @@
+/*
+ * Copyright 2016 Freescale Semiconductor
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/dts-v1/;
+#include "fsl-ls1012a-qds.dtsi"
+
+/ {
+       chosen {
+               stdout-path = &duart0;
+       };
+};
diff --git a/arch/arm/dts/fsl-ls1012a-qds.dtsi b/arch/arm/dts/fsl-ls1012a-qds.dtsi
new file mode 100644
index 0000000..dde7134
--- /dev/null
+++ b/arch/arm/dts/fsl-ls1012a-qds.dtsi
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2016 Freescale Semiconductor
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/include/ "fsl-ls1012a.dtsi"
+
+/ {
+	model = "LS1012A QDS Board";
+	aliases {
+		spi0 = &qspi;
+		spi1 = &dspi0;
+	};
+};
+
+&dspi0 {
+	bus-num = <0>;
+	status = "okay";
+
+	dflash0: n25q128a {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "spi-flash";
+		reg = <0>;
+		spi-max-frequency = <1000000>; /* input clock */
+	};
+
+	dflash1: sst25wf040b {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "spi-flash";
+		spi-max-frequency = <3500000>;
+		reg = <1>;
+	};
+
+	dflash2: en25s64 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "spi-flash";
+		spi-max-frequency = <3500000>;
+		reg = <2>;
+	};
+};
+
+&qspi {
+	bus-num = <0>;
+	status = "okay";
+
+	qflash0: s25fl128s@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "spi-flash";
+		spi-max-frequency = <20000000>;
+		reg = <0>;
+	};
+};
+
+&i2c0 {
+	status = "okay";
+	pca9547@77 {
+		compatible = "philips,pca9547";
+		reg = <0x77>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		i2c@0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x0>;
+
+			rtc@68 {
+				compatible = "dallas,ds3232";
+				reg = <0x68>;
+				/* IRQ10_B */
+				interrupts = <0 150 0x4>;
+			};
+		};
+
+		i2c@2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x2>;
+
+			ina220@40 {
+				compatible = "ti,ina220";
+				reg = <0x40>;
+				shunt-resistor = <1000>;
+			};
+
+			ina220@41 {
+				compatible = "ti,ina220";
+				reg = <0x41>;
+				shunt-resistor = <1000>;
+			};
+		};
+
+		i2c@3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x3>;
+
+			eeprom@56 {
+				compatible = "at24,24c512";
+				reg = <0x56>;
+			};
+
+			eeprom@57 {
+				compatible = "at24,24c512";
+				reg = <0x57>;
+			};
+
+			adt7461a@4c {
+				compatible = "adt7461a";
+				reg = <0x4c>;
+			};
+		};
+	};
+};
+
+&duart0 {
+	status = "okay";
+};
diff --git a/arch/arm/dts/fsl-ls1012a-rdb.dts b/arch/arm/dts/fsl-ls1012a-rdb.dts
new file mode 100644
index 0000000..f683812
--- /dev/null
+++ b/arch/arm/dts/fsl-ls1012a-rdb.dts
@@ -0,0 +1,16 @@
+/*
+ * Device Tree file for Freescale Layerscape-1012A family SoC.
+ *
+ * Copyright 2016, Freescale Semiconductor
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/dts-v1/;
+#include "fsl-ls1012a-rdb.dtsi"
+
+/ {
+       chosen {
+               stdout-path = &duart0;
+       };
+};
diff --git a/arch/arm/dts/fsl-ls1012a-rdb.dtsi b/arch/arm/dts/fsl-ls1012a-rdb.dtsi
new file mode 100644
index 0000000..bf407ae
--- /dev/null
+++ b/arch/arm/dts/fsl-ls1012a-rdb.dtsi
@@ -0,0 +1,39 @@
+/*
+ * Device Tree Include file for Freescale Layerscape-1012A family SoC.
+ *
+ * Copyright 2016, Freescale Semiconductor
+ *
+ * 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/ "fsl-ls1012a.dtsi"
+
+/ {
+	model = "LS1012A RDB Board";
+	aliases {
+		spi0 = &qspi;
+	};
+};
+
+&qspi {
+	bus-num = <0>;
+	status = "okay";
+
+	qflash0: s25fl128s@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "spi-flash";
+		spi-max-frequency = <20000000>;
+		reg = <0>;
+	};
+};
+
+&i2c0 {
+	status = "okay";
+};
+
+&duart0 {
+	status = "okay";
+};
diff --git a/arch/arm/dts/fsl-ls1012a.dtsi b/arch/arm/dts/fsl-ls1012a.dtsi
new file mode 100644
index 0000000..546a87a
--- /dev/null
+++ b/arch/arm/dts/fsl-ls1012a.dtsi
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2016 Freescale Semiconductor
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/include/ "skeleton64.dtsi"
+
+/ {
+	compatible = "fsl,ls1012a";
+	interrupt-parent = <&gic>;
+	cpus {
+		#address-cells = <2>;
+		#size-cells = <0>;
+
+		cpu0: cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53";
+			reg = <0x0 0x0>;
+			clocks = <&clockgen 1 0>;
+		};
+
+	};
+
+	sysclk: sysclk {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <100000000>;
+		clock-output-names = "sysclk";
+	};
+
+	gic: interrupt-controller@1400000 {
+		compatible = "arm,gic-400";
+		#interrupt-cells = <3>;
+		interrupt-controller;
+		reg = <0x0 0x1401000 0 0x1000>, /* GICD */
+		      <0x0 0x1402000 0 0x2000>, /* GICC */
+		      <0x0 0x1404000 0 0x2000>, /* GICH */
+		      <0x0 0x1406000 0 0x2000>; /* GICV */
+		interrupts = <1 9 0xf08>;
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		clockgen: clocking@1ee1000 {
+			compatible = "fsl,ls1012a-clockgen";
+			reg = <0x0 0x1ee1000 0x0 0x1000>;
+			#clock-cells = <2>;
+			clocks = <&sysclk>;
+		};
+
+		dspi0: dspi@2100000 {
+			compatible = "fsl,vf610-dspi";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x0 0x2100000 0x0 0x10000>;
+			interrupts = <0 64 0x4>;
+			clock-names = "dspi";
+			clocks = <&clockgen 4 0>;
+			num-cs = <6>;
+			big-endian;
+			status = "disabled";
+		};
+
+
+		i2c0: i2c@2180000 {
+			compatible = "fsl,vf610-i2c";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x0 0x2180000 0x0 0x10000>;
+			interrupts = <0 56 0x4>;
+			clock-names = "i2c";
+			clocks = <&clockgen 4 0>;
+			status = "disabled";
+		};
+
+		i2c1: i2c@2190000 {
+			compatible = "fsl,vf610-i2c";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x0 0x2190000 0x0 0x10000>;
+			interrupts = <0 57 0x4>;
+			clock-names = "i2c";
+			clocks = <&clockgen 4 0>;
+			status = "disabled";
+		};
+
+		duart0: serial@21c0500 {
+			compatible = "fsl,ns16550", "ns16550a";
+			reg = <0x00 0x21c0500 0x0 0x100>;
+			interrupts = <0 54 0x4>;
+			clocks = <&clockgen 4 0>;
+		};
+
+		duart1: serial@21c0600 {
+			compatible = "fsl,ns16550", "ns16550a";
+			reg = <0x00 0x21c0600 0x0 0x100>;
+			interrupts = <0 54 0x4>;
+			clocks = <&clockgen 4 0>;
+		};
+
+		qspi: quadspi@1550000 {
+			compatible = "fsl,vf610-qspi";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x0 0x1550000 0x0 0x10000>,
+				<0x0 0x40000000 0x0 0x4000000>;
+			reg-names = "QuadSPI", "QuadSPI-memory";
+			num-cs = <2>;
+			big-endian;
+			status = "disabled";
+		};
+
+	};
+};
diff --git a/arch/arm/dts/tegra186-p2771-0000.dts b/arch/arm/dts/tegra186-p2771-0000.dts
new file mode 100644
index 0000000..5f29ee4
--- /dev/null
+++ b/arch/arm/dts/tegra186-p2771-0000.dts
@@ -0,0 +1,25 @@
+/dts-v1/;
+
+#include "tegra186.dtsi"
+
+/ {
+	model = "NVIDIA P2771-0000";
+	compatible = "nvidia,p2771-0000", "nvidia,tegra186";
+
+	chosen {
+		stdout-path = &uarta;
+	};
+
+	aliases {
+		sdhci0 = "/sdhci@3460000";
+	};
+
+	memory {
+		reg = <0x0 0x80000000 0x0 0x60000000>;
+	};
+
+	sdhci@3460000 {
+		status = "okay";
+		bus-width = <8>;
+	};
+};
diff --git a/arch/arm/dts/tegra186.dtsi b/arch/arm/dts/tegra186.dtsi
new file mode 100644
index 0000000..18b6a26
--- /dev/null
+++ b/arch/arm/dts/tegra186.dtsi
@@ -0,0 +1,56 @@
+#include "skeleton.dtsi"
+#include <dt-bindings/gpio/tegra-gpio.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+	compatible = "nvidia,tegra186";
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	gpio@2200000 {
+		compatible = "nvidia,tegra186-gpio";
+		reg-names = "security", "gpio";
+		reg =
+			<0x0 0x2200000 0x0 0x10000>,
+			<0x0 0x2210000 0x0 0x10000>;
+		interrupts =
+			<GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>,
+			<GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>,
+			<GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>,
+			<GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>,
+			<GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>,
+			<GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	uarta: serial@3100000 {
+		compatible = "nvidia,tegra186-uart", "nvidia,tegra20-uart";
+		reg = <0x0 0x03100000 0x0 0x10000>;
+		reg-shift = <2>;
+		status = "disabled";
+	};
+
+	sdhci@3460000 {
+		compatible = "nvidia,tegra186-sdhci";
+		reg = <0x0 0x03460000 0x0 0x200>;
+		interrupts = <GIC_SPI 31 0x04>;
+		status = "disabled";
+	};
+
+	gpio@c2f0000 {
+		compatible = "nvidia,tegra186-gpio-aon";
+		reg-names = "security", "gpio";
+		reg =
+			<0x0 0xc2f0000 0x0 0x1000>,
+			<0x0 0xc2f1000 0x0 0x1000>;
+		interrupts =
+			<GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+};
diff --git a/arch/arm/dts/zynqmp-zc1751-xm018-dc4.dts b/arch/arm/dts/zynqmp-zc1751-xm018-dc4.dts
new file mode 100644
index 0000000..03f1ad7
--- /dev/null
+++ b/arch/arm/dts/zynqmp-zc1751-xm018-dc4.dts
@@ -0,0 +1,212 @@
+/*
+ * dts file for Xilinx ZynqMP zc1751-xm018-dc4
+ *
+ * (C) Copyright 2015 - 2016, Xilinx, Inc.
+ *
+ * Michal Simek <michal.simek@xilinx.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+/dts-v1/;
+
+#include "zynqmp.dtsi"
+#include "zynqmp-clk.dtsi"
+
+/ {
+	model = "ZynqMP zc1751-xm018-dc4";
+	compatible = "xlnx,zynqmp-zc1751", "xlnx,zynqmp";
+
+	aliases {
+		can0 = &can0;
+		can1 = &can1;
+		ethernet0 = &gem0;
+		ethernet1 = &gem1;
+		ethernet2 = &gem2;
+		ethernet3 = &gem3;
+		gpio0 = &gpio;
+		i2c0 = &i2c0;
+		i2c1 = &i2c1;
+		rtc0 = &rtc;
+		serial0 = &uart0;
+		serial1 = &uart1;
+		spi0 = &qspi;
+	};
+
+	chosen {
+		bootargs = "earlycon";
+		stdout-path = "serial0:115200n8";
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x0 0x0 0x0 0x80000000>, <0x8 0x00000000 0x0 0x80000000>;
+	};
+};
+
+&can0 {
+	status = "okay";
+};
+
+&can1 {
+	status = "okay";
+};
+
+/* fpd_dma clk 667MHz, lpd_dma 500MHz */
+&fpd_dma_chan1 {
+	status = "okay";
+	xlnx,include-sg; /* for testing purpose */
+	xlnx,overfetch; /* for testing purpose */
+	xlnx,ratectrl = <0>; /* for testing purpose */
+	xlnx,src-issue = <31>;
+};
+
+&fpd_dma_chan2 {
+	status = "okay";
+	xlnx,ratectrl = <100>; /* for testing purpose */
+	xlnx,src-issue = <4>; /* for testing purpose */
+};
+
+&fpd_dma_chan3 {
+	status = "okay";
+};
+
+&fpd_dma_chan4 {
+	status = "okay";
+	xlnx,include-sg; /* for testing purpose */
+};
+
+&fpd_dma_chan5 {
+	status = "okay";
+};
+
+&fpd_dma_chan6 {
+	status = "okay";
+	xlnx,include-sg; /* for testing purpose */
+};
+
+&fpd_dma_chan7 {
+	status = "okay";
+};
+
+&fpd_dma_chan8 {
+	status = "okay";
+	xlnx,include-sg; /* for testing purpose */
+};
+
+&lpd_dma_chan1 {
+	status = "okay";
+};
+
+&lpd_dma_chan2 {
+	status = "okay";
+};
+
+&lpd_dma_chan3 {
+	status = "okay";
+};
+
+&lpd_dma_chan4 {
+	status = "okay";
+};
+
+&lpd_dma_chan5 {
+	status = "okay";
+};
+
+&lpd_dma_chan6 {
+	status = "okay";
+};
+
+&lpd_dma_chan7 {
+	status = "okay";
+};
+
+&lpd_dma_chan8 {
+	status = "okay";
+};
+
+&xlnx_dp {
+	status = "okay";
+};
+
+&xlnx_dpdma {
+	status = "okay";
+};
+
+&gem0 {
+	status = "okay";
+	local-mac-address = [00 0a 35 00 02 90];
+	phy-mode = "rgmii-id";
+	phy-handle = <&ethernet_phy0>;
+	ethernet_phy0: ethernet-phy@0 { /* Marvell 88e1512 */
+		reg = <0>;
+	};
+	ethernet_phy7: ethernet-phy@7 { /* Vitesse VSC8211 */
+		reg = <7>;
+	};
+	ethernet_phy3: ethernet-phy@3 { /* Realtek RTL8211DN */
+		reg = <3>;
+	};
+	ethernet_phy8: ethernet-phy@8 { /* Vitesse VSC8211 */
+		reg = <8>;
+	};
+};
+
+&gem1 {
+	status = "okay";
+	local-mac-address = [00 0a 35 00 02 91];
+	phy-mode = "rgmii-id";
+	phy-handle = <&ethernet_phy7>;
+};
+
+&gem2 {
+	status = "okay";
+	local-mac-address = [00 0a 35 00 02 92];
+	phy-mode = "rgmii-id";
+	phy-handle = <&ethernet_phy3>;
+};
+
+&gem3 {
+	status = "okay";
+	local-mac-address = [00 0a 35 00 02 93];
+	phy-mode = "rgmii-id";
+	phy-handle = <&ethernet_phy8>;
+};
+
+&gpio {
+	status = "okay";
+};
+
+&gpu {
+	status = "okay";
+};
+
+&i2c0 {
+	clock-frequency = <400000>;
+	status = "okay";
+};
+
+&i2c1 {
+	clock-frequency = <400000>;
+	status = "okay";
+};
+
+&rtc {
+	status = "okay";
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&uart1 {
+	status = "okay";
+};
+
+&watchdog0 {
+	status = "okay";
+};
diff --git a/arch/arm/include/asm/arch-fsl-layerscape/config.h b/arch/arm/include/asm/arch-fsl-layerscape/config.h
index fbdaa52..44fe0c0 100644
--- a/arch/arm/include/asm/arch-fsl-layerscape/config.h
+++ b/arch/arm/include/asm/arch-fsl-layerscape/config.h
@@ -14,8 +14,11 @@
 #else
 #define CONFIG_SYS_FSL_DDRC_ARM_GEN3	/* Enable Freescale ARM DDR3 driver */
 #endif
+
+#ifndef CONFIG_LS1012A
 #define CONFIG_SYS_FSL_DDR		/* Freescale DDR driver */
 #define CONFIG_SYS_FSL_DDR_VER		FSL_DDR_VER_5_0
+#endif
 
 /*
  * Reserve secure memory
@@ -200,6 +203,32 @@
 #define CONFIG_SYS_FSL_ERRATUM_A009942
 #define CONFIG_SYS_FSL_ERRATUM_A009660
 #define CONFIG_SYS_FSL_MAX_NUM_OF_SEC		1
+#elif defined(CONFIG_LS1012A)
+#define CONFIG_MAX_CPUS                         1
+#define CONFIG_SYS_CACHELINE_SIZE		64
+#define CONFIG_NUM_DDR_CONTROLLERS		1
+#define CONFIG_SYS_CCSRBAR_DEFAULT		0x01000000
+#define CONFIG_SYS_FSL_SEC_COMPAT		5
+#undef	CONFIG_SYS_FSL_DDRC_ARM_GEN3
+
+#define CONFIG_SYS_FSL_OCRAM_BASE		0x10000000 /* initial RAM */
+#define CONFIG_SYS_FSL_OCRAM_SIZE		0x200000 /* 2 MiB */
+
+#define GICD_BASE		0x01401000
+#define GICC_BASE		0x01402000
+
+#define CONFIG_SYS_FSL_CCSR_GUR_BE
+#define CONFIG_SYS_FSL_CCSR_SCFG_BE
+#define CONFIG_SYS_FSL_ESDHC_BE
+#define CONFIG_SYS_FSL_WDOG_BE
+#define CONFIG_SYS_FSL_DSPI_BE
+#define CONFIG_SYS_FSL_QSPI_BE
+#define CONFIG_SYS_FSL_PEX_LUT_BE
+
+#define SRDS_MAX_LANES		4
+#define CONFIG_SYS_FSL_SRDS_1
+#define CONFIG_SYS_FSL_PCIE_COMPAT		"fsl,qoriq-pcie-v2.4"
+#define CONFIG_SYS_FSL_SEC_BE
 #else
 #error SoC not defined
 #endif
diff --git a/arch/arm/include/asm/arch-fsl-layerscape/cpu.h b/arch/arm/include/asm/arch-fsl-layerscape/cpu.h
index 702b9fa..1cebe2f 100644
--- a/arch/arm/include/asm/arch-fsl-layerscape/cpu.h
+++ b/arch/arm/include/asm/arch-fsl-layerscape/cpu.h
@@ -14,6 +14,7 @@
 	CPU_TYPE_ENTRY(LS1043, LS1043, 4),
 	CPU_TYPE_ENTRY(LS1023, LS1023, 2),
 	CPU_TYPE_ENTRY(LS2040, LS2040, 4),
+	CPU_TYPE_ENTRY(LS1012, LS1012, 1),
 };
 
 #ifndef CONFIG_SYS_DCACHE_OFF
diff --git a/arch/arm/include/asm/arch-fsl-layerscape/fsl_serdes.h b/arch/arm/include/asm/arch-fsl-layerscape/fsl_serdes.h
index f71c2c1..487cba8 100644
--- a/arch/arm/include/asm/arch-fsl-layerscape/fsl_serdes.h
+++ b/arch/arm/include/asm/arch-fsl-layerscape/fsl_serdes.h
@@ -55,7 +55,7 @@
 	FSL_SRDS_1  = 0,
 	FSL_SRDS_2  = 1,
 };
-#elif defined(CONFIG_LS1043A)
+#elif defined(CONFIG_FSL_LSCH2)
 enum srds_prtcl {
 	NONE = 0,
 	PCIE1,
@@ -134,6 +134,7 @@
 	SGMII_2500_FM2_DTSEC6,
 	SGMII_2500_FM2_DTSEC9,
 	SGMII_2500_FM2_DTSEC10,
+	TX_CLK,
 	SERDES_PRCTL_COUNT
 };
 
diff --git a/arch/arm/include/asm/arch-fsl-layerscape/immap_lsch2.h b/arch/arm/include/asm/arch-fsl-layerscape/immap_lsch2.h
index 57b99d4..e98e055 100644
--- a/arch/arm/include/asm/arch-fsl-layerscape/immap_lsch2.h
+++ b/arch/arm/include/asm/arch-fsl-layerscape/immap_lsch2.h
@@ -60,7 +60,11 @@
 #define CONFIG_SYS_PCIE2_PHYS_ADDR		0x4800000000ULL
 #define CONFIG_SYS_PCIE3_PHYS_ADDR		0x5000000000ULL
 /* LUT registers */
+#ifdef CONFIG_LS1012A
+#define PCIE_LUT_BASE				0xC0000
+#else
 #define PCIE_LUT_BASE				0x10000
+#endif
 #define PCIE_LUT_LCTRL0				0x7F8
 #define PCIE_LUT_DBG				0x7FC
 
diff --git a/arch/arm/include/asm/arch-fsl-layerscape/ns_access.h b/arch/arm/include/asm/arch-fsl-layerscape/ns_access.h
index a3ccdb0..db76066 100644
--- a/arch/arm/include/asm/arch-fsl-layerscape/ns_access.h
+++ b/arch/arm/include/asm/arch-fsl-layerscape/ns_access.h
@@ -69,7 +69,12 @@
 	CSU_CSLX_IIC4 = 77,
 	CSU_CSLX_WDT4,
 	CSU_CSLX_WDT3,
+	CSU_CSLX_ESDHC2 = 80,
 	CSU_CSLX_WDT5 = 81,
+	CSU_CSLX_SAI2,
+	CSU_CSLX_SAI1,
+	CSU_CSLX_SAI4,
+	CSU_CSLX_SAI3,
 	CSU_CSLX_FTM2 = 86,
 	CSU_CSLX_FTM1,
 	CSU_CSLX_FTM4,
@@ -143,7 +148,12 @@
 	 {CSU_CSLX_IIC4, CSU_ALL_RW},
 	 {CSU_CSLX_WDT4, CSU_ALL_RW},
 	 {CSU_CSLX_WDT3, CSU_ALL_RW},
+	 {CSU_CSLX_ESDHC2, CSU_ALL_RW},
 	 {CSU_CSLX_WDT5, CSU_ALL_RW},
+	 {CSU_CSLX_SAI2, CSU_ALL_RW},
+	 {CSU_CSLX_SAI1, CSU_ALL_RW},
+	 {CSU_CSLX_SAI4, CSU_ALL_RW},
+	 {CSU_CSLX_SAI3, CSU_ALL_RW},
 	 {CSU_CSLX_FTM2, CSU_ALL_RW},
 	 {CSU_CSLX_FTM1, CSU_ALL_RW},
 	 {CSU_CSLX_FTM4, CSU_ALL_RW},
diff --git a/arch/arm/include/asm/arch-fsl-layerscape/soc.h b/arch/arm/include/asm/arch-fsl-layerscape/soc.h
index 831d817..02ecc62 100644
--- a/arch/arm/include/asm/arch-fsl-layerscape/soc.h
+++ b/arch/arm/include/asm/arch-fsl-layerscape/soc.h
@@ -41,6 +41,7 @@
 	{ .name = #n, .soc_ver = SVR_##v, .num_cores = (nc)}
 
 #define SVR_WO_E		0xFFFFFE
+#define SVR_LS1012		0x870400
 #define SVR_LS1043		0x879200
 #define SVR_LS1023		0x879208
 #define SVR_LS2045		0x870120
diff --git a/arch/arm/include/asm/arch-tegra/gpio.h b/arch/arm/include/asm/arch-tegra/gpio.h
index daf5698..db60864 100644
--- a/arch/arm/include/asm/arch-tegra/gpio.h
+++ b/arch/arm/include/asm/arch-tegra/gpio.h
@@ -6,6 +6,8 @@
 #ifndef _TEGRA_GPIO_H_
 #define _TEGRA_GPIO_H_
 
+#include <dt-bindings/gpio/tegra-gpio.h>
+
 #define TEGRA_GPIOS_PER_PORT	8
 #define TEGRA_PORTS_PER_BANK	4
 #define MAX_NUM_GPIOS           (TEGRA_GPIO_PORTS * TEGRA_GPIO_BANKS * 8)
diff --git a/arch/arm/include/asm/arch-tegra/tegra_mmc.h b/arch/arm/include/asm/arch-tegra/tegra_mmc.h
index a20bdaa..75e56c4 100644
--- a/arch/arm/include/asm/arch-tegra/tegra_mmc.h
+++ b/arch/arm/include/asm/arch-tegra/tegra_mmc.h
@@ -134,7 +134,9 @@
 	int id;			/* device id/number, 0-3 */
 	int enabled;		/* 1 to enable, 0 to disable */
 	int width;		/* Bus Width, 1, 4 or 8 */
+#ifndef CONFIG_TEGRA186
 	enum periph_id mmc_id;	/* Peripheral ID: PERIPH_ID_... */
+#endif
 	struct gpio_desc cd_gpio;	/* Change Detect GPIO */
 	struct gpio_desc pwr_gpio;	/* Power GPIO */
 	struct gpio_desc wp_gpio;	/* Write Protect GPIO */
diff --git a/arch/arm/include/asm/arch-tegra124/gpio.h b/arch/arm/include/asm/arch-tegra124/gpio.h
index 1a6dcb8..ba748a5 100644
--- a/arch/arm/include/asm/arch-tegra124/gpio.h
+++ b/arch/arm/include/asm/arch-tegra124/gpio.h
@@ -41,263 +41,4 @@
 	struct gpio_ctlr_bank gpio_bank[TEGRA_GPIO_BANKS];
 };
 
-enum gpio_pin {
-	GPIO_PA0 = 0,	/* pin 0 */
-	GPIO_PA1,
-	GPIO_PA2,
-	GPIO_PA3,
-	GPIO_PA4,
-	GPIO_PA5,
-	GPIO_PA6,
-	GPIO_PA7,
-	GPIO_PB0,	/* pin 8 */
-	GPIO_PB1,
-	GPIO_PB2,
-	GPIO_PB3,
-	GPIO_PB4,
-	GPIO_PB5,
-	GPIO_PB6,
-	GPIO_PB7,
-	GPIO_PC0,	/* pin 16 */
-	GPIO_PC1,
-	GPIO_PC2,
-	GPIO_PC3,
-	GPIO_PC4,
-	GPIO_PC5,
-	GPIO_PC6,
-	GPIO_PC7,
-	GPIO_PD0,	/* pin 24 */
-	GPIO_PD1,
-	GPIO_PD2,
-	GPIO_PD3,
-	GPIO_PD4,
-	GPIO_PD5,
-	GPIO_PD6,
-	GPIO_PD7,
-	GPIO_PE0,	/* pin 32 */
-	GPIO_PE1,
-	GPIO_PE2,
-	GPIO_PE3,
-	GPIO_PE4,
-	GPIO_PE5,
-	GPIO_PE6,
-	GPIO_PE7,
-	GPIO_PF0,	/* pin 40 */
-	GPIO_PF1,
-	GPIO_PF2,
-	GPIO_PF3,
-	GPIO_PF4,
-	GPIO_PF5,
-	GPIO_PF6,
-	GPIO_PF7,
-	GPIO_PG0,	/* pin 48 */
-	GPIO_PG1,
-	GPIO_PG2,
-	GPIO_PG3,
-	GPIO_PG4,
-	GPIO_PG5,
-	GPIO_PG6,
-	GPIO_PG7,
-	GPIO_PH0,	/* pin 56 */
-	GPIO_PH1,
-	GPIO_PH2,
-	GPIO_PH3,
-	GPIO_PH4,
-	GPIO_PH5,
-	GPIO_PH6,
-	GPIO_PH7,
-	GPIO_PI0,	/* pin 64 */
-	GPIO_PI1,
-	GPIO_PI2,
-	GPIO_PI3,
-	GPIO_PI4,
-	GPIO_PI5,
-	GPIO_PI6,
-	GPIO_PI7,
-	GPIO_PJ0,	/* pin 72 */
-	GPIO_PJ1,
-	GPIO_PJ2,
-	GPIO_PJ3,
-	GPIO_PJ4,
-	GPIO_PJ5,
-	GPIO_PJ6,
-	GPIO_PJ7,
-	GPIO_PK0,	/* pin 80 */
-	GPIO_PK1,
-	GPIO_PK2,
-	GPIO_PK3,
-	GPIO_PK4,
-	GPIO_PK5,
-	GPIO_PK6,
-	GPIO_PK7,
-	GPIO_PL0,	/* pin 88 */
-	GPIO_PL1,
-	GPIO_PL2,
-	GPIO_PL3,
-	GPIO_PL4,
-	GPIO_PL5,
-	GPIO_PL6,
-	GPIO_PL7,
-	GPIO_PM0,	/* pin 96 */
-	GPIO_PM1,
-	GPIO_PM2,
-	GPIO_PM3,
-	GPIO_PM4,
-	GPIO_PM5,
-	GPIO_PM6,
-	GPIO_PM7,
-	GPIO_PN0,	/* pin 104 */
-	GPIO_PN1,
-	GPIO_PN2,
-	GPIO_PN3,
-	GPIO_PN4,
-	GPIO_PN5,
-	GPIO_PN6,
-	GPIO_PN7,
-	GPIO_PO0,	/* pin 112 */
-	GPIO_PO1,
-	GPIO_PO2,
-	GPIO_PO3,
-	GPIO_PO4,
-	GPIO_PO5,
-	GPIO_PO6,
-	GPIO_PO7,
-	GPIO_PP0,	/* pin 120 */
-	GPIO_PP1,
-	GPIO_PP2,
-	GPIO_PP3,
-	GPIO_PP4,
-	GPIO_PP5,
-	GPIO_PP6,
-	GPIO_PP7,
-	GPIO_PQ0,	/* pin 128 */
-	GPIO_PQ1,
-	GPIO_PQ2,
-	GPIO_PQ3,
-	GPIO_PQ4,
-	GPIO_PQ5,
-	GPIO_PQ6,
-	GPIO_PQ7,
-	GPIO_PR0,	/* pin 136 */
-	GPIO_PR1,
-	GPIO_PR2,
-	GPIO_PR3,
-	GPIO_PR4,
-	GPIO_PR5,
-	GPIO_PR6,
-	GPIO_PR7,
-	GPIO_PS0,	/* pin 144 */
-	GPIO_PS1,
-	GPIO_PS2,
-	GPIO_PS3,
-	GPIO_PS4,
-	GPIO_PS5,
-	GPIO_PS6,
-	GPIO_PS7,
-	GPIO_PT0,	/* pin 152 */
-	GPIO_PT1,
-	GPIO_PT2,
-	GPIO_PT3,
-	GPIO_PT4,
-	GPIO_PT5,
-	GPIO_PT6,
-	GPIO_PT7,
-	GPIO_PU0,	/* pin 160 */
-	GPIO_PU1,
-	GPIO_PU2,
-	GPIO_PU3,
-	GPIO_PU4,
-	GPIO_PU5,
-	GPIO_PU6,
-	GPIO_PU7,
-	GPIO_PV0,	/* pin 168 */
-	GPIO_PV1,
-	GPIO_PV2,
-	GPIO_PV3,
-	GPIO_PV4,
-	GPIO_PV5,
-	GPIO_PV6,
-	GPIO_PV7,
-	GPIO_PW0,	/* pin 176 */
-	GPIO_PW1,
-	GPIO_PW2,
-	GPIO_PW3,
-	GPIO_PW4,
-	GPIO_PW5,
-	GPIO_PW6,
-	GPIO_PW7,
-	GPIO_PX0,	/* pin 184 */
-	GPIO_PX1,
-	GPIO_PX2,
-	GPIO_PX3,
-	GPIO_PX4,
-	GPIO_PX5,
-	GPIO_PX6,
-	GPIO_PX7,
-	GPIO_PY0,	/* pin 192 */
-	GPIO_PY1,
-	GPIO_PY2,
-	GPIO_PY3,
-	GPIO_PY4,
-	GPIO_PY5,
-	GPIO_PY6,
-	GPIO_PY7,
-	GPIO_PZ0,	/* pin 200 */
-	GPIO_PZ1,
-	GPIO_PZ2,
-	GPIO_PZ3,
-	GPIO_PZ4,
-	GPIO_PZ5,
-	GPIO_PZ6,
-	GPIO_PZ7,
-	GPIO_PAA0,	/* pin 208 */
-	GPIO_PAA1,
-	GPIO_PAA2,
-	GPIO_PAA3,
-	GPIO_PAA4,
-	GPIO_PAA5,
-	GPIO_PAA6,
-	GPIO_PAA7,
-	GPIO_PBB0,	/* pin 216 */
-	GPIO_PBB1,
-	GPIO_PBB2,
-	GPIO_PBB3,
-	GPIO_PBB4,
-	GPIO_PBB5,
-	GPIO_PBB6,
-	GPIO_PBB7,
-	GPIO_PCC0,	/* pin 224 */
-	GPIO_PCC1,
-	GPIO_PCC2,
-	GPIO_PCC3,
-	GPIO_PCC4,
-	GPIO_PCC5,
-	GPIO_PCC6,
-	GPIO_PCC7,
-	GPIO_PDD0,	/* pin 232 */
-	GPIO_PDD1,
-	GPIO_PDD2,
-	GPIO_PDD3,
-	GPIO_PDD4,
-	GPIO_PDD5,
-	GPIO_PDD6,
-	GPIO_PDD7,
-	GPIO_PEE0,	/* pin 240 */
-	GPIO_PEE1,
-	GPIO_PEE2,
-	GPIO_PEE3,
-	GPIO_PEE4,
-	GPIO_PEE5,
-	GPIO_PEE6,
-	GPIO_PEE7,
-	GPIO_PFF0,	/* pin 248 */
-	GPIO_PFF1,
-	GPIO_PFF2,
-	GPIO_PFF3,
-	GPIO_PFF4,
-	GPIO_PFF5,
-	GPIO_PFF6,
-	GPIO_PFF7,	/* pin 255 */
-};
-
 #endif	/* _TEGRA124_GPIO_H_ */
diff --git a/arch/arm/include/asm/arch-tegra186/gpio.h b/arch/arm/include/asm/arch-tegra186/gpio.h
new file mode 100644
index 0000000..aaecfc7
--- /dev/null
+++ b/arch/arm/include/asm/arch-tegra186/gpio.h
@@ -0,0 +1,10 @@
+/*
+ * Copyright (c) 2016, NVIDIA CORPORATION.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef _TEGRA186_GPIO_H_
+#define _TEGRA186_GPIO_H_
+
+#endif
diff --git a/arch/arm/include/asm/arch-tegra186/tegra.h b/arch/arm/include/asm/arch-tegra186/tegra.h
new file mode 100644
index 0000000..8031f23
--- /dev/null
+++ b/arch/arm/include/asm/arch-tegra186/tegra.h
@@ -0,0 +1,16 @@
+/*
+ * (C) Copyright 2013-2016, NVIDIA CORPORATION.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef _TEGRA186_TEGRA_H_
+#define _TEGRA186_TEGRA_H_
+
+#define GICD_BASE		0x03881000	/* Generic Int Cntrlr Distrib */
+#define GICC_BASE		0x03882000	/* Generic Int Cntrlr CPU I/F */
+#define NV_PA_SDRAM_BASE	0x80000000
+
+#include <asm/arch-tegra/tegra.h>
+
+#endif
diff --git a/arch/arm/include/asm/arch-tegra20/gpio.h b/arch/arm/include/asm/arch-tegra20/gpio.h
index b40b1ff..af301e7 100644
--- a/arch/arm/include/asm/arch-tegra20/gpio.h
+++ b/arch/arm/include/asm/arch-tegra20/gpio.h
@@ -33,231 +33,4 @@
 	struct gpio_ctlr_bank gpio_bank[TEGRA_GPIO_BANKS];
 };
 
-enum gpio_pin {
-	GPIO_PA0 = 0,	/* pin 0 */
-	GPIO_PA1,
-	GPIO_PA2,
-	GPIO_PA3,
-	GPIO_PA4,
-	GPIO_PA5,
-	GPIO_PA6,
-	GPIO_PA7,
-	GPIO_PB0,	/* pin 8 */
-	GPIO_PB1,
-	GPIO_PB2,
-	GPIO_PB3,
-	GPIO_PB4,
-	GPIO_PB5,
-	GPIO_PB6,
-	GPIO_PB7,
-	GPIO_PC0,	/* pin 16 */
-	GPIO_PC1,
-	GPIO_PC2,
-	GPIO_PC3,
-	GPIO_PC4,
-	GPIO_PC5,
-	GPIO_PC6,
-	GPIO_PC7,
-	GPIO_PD0,	/* pin 24 */
-	GPIO_PD1,
-	GPIO_PD2,
-	GPIO_PD3,
-	GPIO_PD4,
-	GPIO_PD5,
-	GPIO_PD6,
-	GPIO_PD7,
-	GPIO_PE0,	/* pin 32 */
-	GPIO_PE1,
-	GPIO_PE2,
-	GPIO_PE3,
-	GPIO_PE4,
-	GPIO_PE5,
-	GPIO_PE6,
-	GPIO_PE7,
-	GPIO_PF0,	/* pin 40 */
-	GPIO_PF1,
-	GPIO_PF2,
-	GPIO_PF3,
-	GPIO_PF4,
-	GPIO_PF5,
-	GPIO_PF6,
-	GPIO_PF7,
-	GPIO_PG0,	/* pin 48 */
-	GPIO_PG1,
-	GPIO_PG2,
-	GPIO_PG3,
-	GPIO_PG4,
-	GPIO_PG5,
-	GPIO_PG6,
-	GPIO_PG7,
-	GPIO_PH0,	/* pin 56 */
-	GPIO_PH1,
-	GPIO_PH2,
-	GPIO_PH3,
-	GPIO_PH4,
-	GPIO_PH5,
-	GPIO_PH6,
-	GPIO_PH7,
-	GPIO_PI0,	/* pin 64 */
-	GPIO_PI1,
-	GPIO_PI2,
-	GPIO_PI3,
-	GPIO_PI4,
-	GPIO_PI5,
-	GPIO_PI6,
-	GPIO_PI7,
-	GPIO_PJ0,	/* pin 72 */
-	GPIO_PJ1,
-	GPIO_PJ2,
-	GPIO_PJ3,
-	GPIO_PJ4,
-	GPIO_PJ5,
-	GPIO_PJ6,
-	GPIO_PJ7,
-	GPIO_PK0,	/* pin 80 */
-	GPIO_PK1,
-	GPIO_PK2,
-	GPIO_PK3,
-	GPIO_PK4,
-	GPIO_PK5,
-	GPIO_PK6,
-	GPIO_PK7,
-	GPIO_PL0,	/* pin 88 */
-	GPIO_PL1,
-	GPIO_PL2,
-	GPIO_PL3,
-	GPIO_PL4,
-	GPIO_PL5,
-	GPIO_PL6,
-	GPIO_PL7,
-	GPIO_PM0,	/* pin 96 */
-	GPIO_PM1,
-	GPIO_PM2,
-	GPIO_PM3,
-	GPIO_PM4,
-	GPIO_PM5,
-	GPIO_PM6,
-	GPIO_PM7,
-	GPIO_PN0,	/* pin 104 */
-	GPIO_PN1,
-	GPIO_PN2,
-	GPIO_PN3,
-	GPIO_PN4,
-	GPIO_PN5,
-	GPIO_PN6,
-	GPIO_PN7,
-	GPIO_PO0,	/* pin 112 */
-	GPIO_PO1,
-	GPIO_PO2,
-	GPIO_PO3,
-	GPIO_PO4,
-	GPIO_PO5,
-	GPIO_PO6,
-	GPIO_PO7,
-	GPIO_PP0,	/* pin 120 */
-	GPIO_PP1,
-	GPIO_PP2,
-	GPIO_PP3,
-	GPIO_PP4,
-	GPIO_PP5,
-	GPIO_PP6,
-	GPIO_PP7,
-	GPIO_PQ0,	/* pin 128 */
-	GPIO_PQ1,
-	GPIO_PQ2,
-	GPIO_PQ3,
-	GPIO_PQ4,
-	GPIO_PQ5,
-	GPIO_PQ6,
-	GPIO_PQ7,
-	GPIO_PR0,	/* pin 136 */
-	GPIO_PR1,
-	GPIO_PR2,
-	GPIO_PR3,
-	GPIO_PR4,
-	GPIO_PR5,
-	GPIO_PR6,
-	GPIO_PR7,
-	GPIO_PS0,	/* pin 144 */
-	GPIO_PS1,
-	GPIO_PS2,
-	GPIO_PS3,
-	GPIO_PS4,
-	GPIO_PS5,
-	GPIO_PS6,
-	GPIO_PS7,
-	GPIO_PT0,	/* pin 152 */
-	GPIO_PT1,
-	GPIO_PT2,
-	GPIO_PT3,
-	GPIO_PT4,
-	GPIO_PT5,
-	GPIO_PT6,
-	GPIO_PT7,
-	GPIO_PU0,	/* pin 160 */
-	GPIO_PU1,
-	GPIO_PU2,
-	GPIO_PU3,
-	GPIO_PU4,
-	GPIO_PU5,
-	GPIO_PU6,
-	GPIO_PU7,
-	GPIO_PV0,	/* pin 168 */
-	GPIO_PV1,
-	GPIO_PV2,
-	GPIO_PV3,
-	GPIO_PV4,
-	GPIO_PV5,
-	GPIO_PV6,
-	GPIO_PV7,
-	GPIO_PW0,	/* pin 176 */
-	GPIO_PW1,
-	GPIO_PW2,
-	GPIO_PW3,
-	GPIO_PW4,
-	GPIO_PW5,
-	GPIO_PW6,
-	GPIO_PW7,
-	GPIO_PX0,	/* pin 184 */
-	GPIO_PX1,
-	GPIO_PX2,
-	GPIO_PX3,
-	GPIO_PX4,
-	GPIO_PX5,
-	GPIO_PX6,
-	GPIO_PX7,
-	GPIO_PY0,	/* pin 192 */
-	GPIO_PY1,
-	GPIO_PY2,
-	GPIO_PY3,
-	GPIO_PY4,
-	GPIO_PY5,
-	GPIO_PY6,
-	GPIO_PY7,
-	GPIO_PZ0,	/* pin 200 */
-	GPIO_PZ1,
-	GPIO_PZ2,
-	GPIO_PZ3,
-	GPIO_PZ4,
-	GPIO_PZ5,
-	GPIO_PZ6,
-	GPIO_PZ7,
-	GPIO_PAA0,	/* pin 208 */
-	GPIO_PAA1,
-	GPIO_PAA2,
-	GPIO_PAA3,
-	GPIO_PAA4,
-	GPIO_PAA5,
-	GPIO_PAA6,
-	GPIO_PAA7,
-	GPIO_PBB0,	/* pin 216 */
-	GPIO_PBB1,
-	GPIO_PBB2,
-	GPIO_PBB3,
-	GPIO_PBB4,
-	GPIO_PBB5,
-	GPIO_PBB6,
-	GPIO_PBB7,	/* pin 223 */
-};
-
 #endif	/* TEGRA20_GPIO_H_ */
diff --git a/arch/arm/include/asm/arch-tegra210/gpio.h b/arch/arm/include/asm/arch-tegra210/gpio.h
index 71af423..389d5b6 100644
--- a/arch/arm/include/asm/arch-tegra210/gpio.h
+++ b/arch/arm/include/asm/arch-tegra210/gpio.h
@@ -41,263 +41,4 @@
 	struct gpio_ctlr_bank gpio_bank[TEGRA_GPIO_BANKS];
 };
 
-enum gpio_pin {
-	GPIO_PA0 = 0,	/* pin 0 */
-	GPIO_PA1,
-	GPIO_PA2,
-	GPIO_PA3,
-	GPIO_PA4,
-	GPIO_PA5,
-	GPIO_PA6,
-	GPIO_PA7,
-	GPIO_PB0,	/* pin 8 */
-	GPIO_PB1,
-	GPIO_PB2,
-	GPIO_PB3,
-	GPIO_PB4,
-	GPIO_PB5,
-	GPIO_PB6,
-	GPIO_PB7,
-	GPIO_PC0,	/* pin 16 */
-	GPIO_PC1,
-	GPIO_PC2,
-	GPIO_PC3,
-	GPIO_PC4,
-	GPIO_PC5,
-	GPIO_PC6,
-	GPIO_PC7,
-	GPIO_PD0,	/* pin 24 */
-	GPIO_PD1,
-	GPIO_PD2,
-	GPIO_PD3,
-	GPIO_PD4,
-	GPIO_PD5,
-	GPIO_PD6,
-	GPIO_PD7,
-	GPIO_PE0,	/* pin 32 */
-	GPIO_PE1,
-	GPIO_PE2,
-	GPIO_PE3,
-	GPIO_PE4,
-	GPIO_PE5,
-	GPIO_PE6,
-	GPIO_PE7,
-	GPIO_PF0,	/* pin 40 */
-	GPIO_PF1,
-	GPIO_PF2,
-	GPIO_PF3,
-	GPIO_PF4,
-	GPIO_PF5,
-	GPIO_PF6,
-	GPIO_PF7,
-	GPIO_PG0,	/* pin 48 */
-	GPIO_PG1,
-	GPIO_PG2,
-	GPIO_PG3,
-	GPIO_PG4,
-	GPIO_PG5,
-	GPIO_PG6,
-	GPIO_PG7,
-	GPIO_PH0,	/* pin 56 */
-	GPIO_PH1,
-	GPIO_PH2,
-	GPIO_PH3,
-	GPIO_PH4,
-	GPIO_PH5,
-	GPIO_PH6,
-	GPIO_PH7,
-	GPIO_PI0,	/* pin 64 */
-	GPIO_PI1,
-	GPIO_PI2,
-	GPIO_PI3,
-	GPIO_PI4,
-	GPIO_PI5,
-	GPIO_PI6,
-	GPIO_PI7,
-	GPIO_PJ0,	/* pin 72 */
-	GPIO_PJ1,
-	GPIO_PJ2,
-	GPIO_PJ3,
-	GPIO_PJ4,
-	GPIO_PJ5,
-	GPIO_PJ6,
-	GPIO_PJ7,
-	GPIO_PK0,	/* pin 80 */
-	GPIO_PK1,
-	GPIO_PK2,
-	GPIO_PK3,
-	GPIO_PK4,
-	GPIO_PK5,
-	GPIO_PK6,
-	GPIO_PK7,
-	GPIO_PL0,	/* pin 88 */
-	GPIO_PL1,
-	GPIO_PL2,
-	GPIO_PL3,
-	GPIO_PL4,
-	GPIO_PL5,
-	GPIO_PL6,
-	GPIO_PL7,
-	GPIO_PM0,	/* pin 96 */
-	GPIO_PM1,
-	GPIO_PM2,
-	GPIO_PM3,
-	GPIO_PM4,
-	GPIO_PM5,
-	GPIO_PM6,
-	GPIO_PM7,
-	GPIO_PN0,	/* pin 104 */
-	GPIO_PN1,
-	GPIO_PN2,
-	GPIO_PN3,
-	GPIO_PN4,
-	GPIO_PN5,
-	GPIO_PN6,
-	GPIO_PN7,
-	GPIO_PO0,	/* pin 112 */
-	GPIO_PO1,
-	GPIO_PO2,
-	GPIO_PO3,
-	GPIO_PO4,
-	GPIO_PO5,
-	GPIO_PO6,
-	GPIO_PO7,
-	GPIO_PP0,	/* pin 120 */
-	GPIO_PP1,
-	GPIO_PP2,
-	GPIO_PP3,
-	GPIO_PP4,
-	GPIO_PP5,
-	GPIO_PP6,
-	GPIO_PP7,
-	GPIO_PQ0,	/* pin 128 */
-	GPIO_PQ1,
-	GPIO_PQ2,
-	GPIO_PQ3,
-	GPIO_PQ4,
-	GPIO_PQ5,
-	GPIO_PQ6,
-	GPIO_PQ7,
-	GPIO_PR0,	/* pin 136 */
-	GPIO_PR1,
-	GPIO_PR2,
-	GPIO_PR3,
-	GPIO_PR4,
-	GPIO_PR5,
-	GPIO_PR6,
-	GPIO_PR7,
-	GPIO_PS0,	/* pin 144 */
-	GPIO_PS1,
-	GPIO_PS2,
-	GPIO_PS3,
-	GPIO_PS4,
-	GPIO_PS5,
-	GPIO_PS6,
-	GPIO_PS7,
-	GPIO_PT0,	/* pin 152 */
-	GPIO_PT1,
-	GPIO_PT2,
-	GPIO_PT3,
-	GPIO_PT4,
-	GPIO_PT5,
-	GPIO_PT6,
-	GPIO_PT7,
-	GPIO_PU0,	/* pin 160 */
-	GPIO_PU1,
-	GPIO_PU2,
-	GPIO_PU3,
-	GPIO_PU4,
-	GPIO_PU5,
-	GPIO_PU6,
-	GPIO_PU7,
-	GPIO_PV0,	/* pin 168 */
-	GPIO_PV1,
-	GPIO_PV2,
-	GPIO_PV3,
-	GPIO_PV4,
-	GPIO_PV5,
-	GPIO_PV6,
-	GPIO_PV7,
-	GPIO_PW0,	/* pin 176 */
-	GPIO_PW1,
-	GPIO_PW2,
-	GPIO_PW3,
-	GPIO_PW4,
-	GPIO_PW5,
-	GPIO_PW6,
-	GPIO_PW7,
-	GPIO_PX0,	/* pin 184 */
-	GPIO_PX1,
-	GPIO_PX2,
-	GPIO_PX3,
-	GPIO_PX4,
-	GPIO_PX5,
-	GPIO_PX6,
-	GPIO_PX7,
-	GPIO_PY0,	/* pin 192 */
-	GPIO_PY1,
-	GPIO_PY2,
-	GPIO_PY3,
-	GPIO_PY4,
-	GPIO_PY5,
-	GPIO_PY6,
-	GPIO_PY7,
-	GPIO_PZ0,	/* pin 200 */
-	GPIO_PZ1,
-	GPIO_PZ2,
-	GPIO_PZ3,
-	GPIO_PZ4,
-	GPIO_PZ5,
-	GPIO_PZ6,
-	GPIO_PZ7,
-	GPIO_PAA0,	/* pin 208 */
-	GPIO_PAA1,
-	GPIO_PAA2,
-	GPIO_PAA3,
-	GPIO_PAA4,
-	GPIO_PAA5,
-	GPIO_PAA6,
-	GPIO_PAA7,
-	GPIO_PBB0,	/* pin 216 */
-	GPIO_PBB1,
-	GPIO_PBB2,
-	GPIO_PBB3,
-	GPIO_PBB4,
-	GPIO_PBB5,
-	GPIO_PBB6,
-	GPIO_PBB7,
-	GPIO_PCC0,	/* pin 224 */
-	GPIO_PCC1,
-	GPIO_PCC2,
-	GPIO_PCC3,
-	GPIO_PCC4,
-	GPIO_PCC5,
-	GPIO_PCC6,
-	GPIO_PCC7,
-	GPIO_PDD0,	/* pin 232 */
-	GPIO_PDD1,
-	GPIO_PDD2,
-	GPIO_PDD3,
-	GPIO_PDD4,
-	GPIO_PDD5,
-	GPIO_PDD6,
-	GPIO_PDD7,
-	GPIO_PEE0,	/* pin 240 */
-	GPIO_PEE1,
-	GPIO_PEE2,
-	GPIO_PEE3,
-	GPIO_PEE4,
-	GPIO_PEE5,
-	GPIO_PEE6,
-	GPIO_PEE7,
-	GPIO_PFF0,	/* pin 248 */
-	GPIO_PFF1,
-	GPIO_PFF2,
-	GPIO_PFF3,
-	GPIO_PFF4,
-	GPIO_PFF5,
-	GPIO_PFF6,
-	GPIO_PFF7,	/* pin 255 */
-};
-
 #endif	/* _TEGRA210_GPIO_H_ */
diff --git a/arch/arm/include/asm/arch-tegra30/gpio.h b/arch/arm/include/asm/arch-tegra30/gpio.h
index d2c6c78..e384327 100644
--- a/arch/arm/include/asm/arch-tegra30/gpio.h
+++ b/arch/arm/include/asm/arch-tegra30/gpio.h
@@ -40,255 +40,4 @@
 	struct gpio_ctlr_bank gpio_bank[TEGRA_GPIO_BANKS];
 };
 
-enum gpio_pin {
-	GPIO_PA0 = 0,	/* pin 0 */
-	GPIO_PA1,
-	GPIO_PA2,
-	GPIO_PA3,
-	GPIO_PA4,
-	GPIO_PA5,
-	GPIO_PA6,
-	GPIO_PA7,
-	GPIO_PB0,	/* pin 8 */
-	GPIO_PB1,
-	GPIO_PB2,
-	GPIO_PB3,
-	GPIO_PB4,
-	GPIO_PB5,
-	GPIO_PB6,
-	GPIO_PB7,
-	GPIO_PC0,	/* pin 16 */
-	GPIO_PC1,
-	GPIO_PC2,
-	GPIO_PC3,
-	GPIO_PC4,
-	GPIO_PC5,
-	GPIO_PC6,
-	GPIO_PC7,
-	GPIO_PD0,	/* pin 24 */
-	GPIO_PD1,
-	GPIO_PD2,
-	GPIO_PD3,
-	GPIO_PD4,
-	GPIO_PD5,
-	GPIO_PD6,
-	GPIO_PD7,
-	GPIO_PE0,	/* pin 32 */
-	GPIO_PE1,
-	GPIO_PE2,
-	GPIO_PE3,
-	GPIO_PE4,
-	GPIO_PE5,
-	GPIO_PE6,
-	GPIO_PE7,
-	GPIO_PF0,	/* pin 40 */
-	GPIO_PF1,
-	GPIO_PF2,
-	GPIO_PF3,
-	GPIO_PF4,
-	GPIO_PF5,
-	GPIO_PF6,
-	GPIO_PF7,
-	GPIO_PG0,	/* pin 48 */
-	GPIO_PG1,
-	GPIO_PG2,
-	GPIO_PG3,
-	GPIO_PG4,
-	GPIO_PG5,
-	GPIO_PG6,
-	GPIO_PG7,
-	GPIO_PH0,	/* pin 56 */
-	GPIO_PH1,
-	GPIO_PH2,
-	GPIO_PH3,
-	GPIO_PH4,
-	GPIO_PH5,
-	GPIO_PH6,
-	GPIO_PH7,
-	GPIO_PI0,	/* pin 64 */
-	GPIO_PI1,
-	GPIO_PI2,
-	GPIO_PI3,
-	GPIO_PI4,
-	GPIO_PI5,
-	GPIO_PI6,
-	GPIO_PI7,
-	GPIO_PJ0,	/* pin 72 */
-	GPIO_PJ1,
-	GPIO_PJ2,
-	GPIO_PJ3,
-	GPIO_PJ4,
-	GPIO_PJ5,
-	GPIO_PJ6,
-	GPIO_PJ7,
-	GPIO_PK0,	/* pin 80 */
-	GPIO_PK1,
-	GPIO_PK2,
-	GPIO_PK3,
-	GPIO_PK4,
-	GPIO_PK5,
-	GPIO_PK6,
-	GPIO_PK7,
-	GPIO_PL0,	/* pin 88 */
-	GPIO_PL1,
-	GPIO_PL2,
-	GPIO_PL3,
-	GPIO_PL4,
-	GPIO_PL5,
-	GPIO_PL6,
-	GPIO_PL7,
-	GPIO_PM0,	/* pin 96 */
-	GPIO_PM1,
-	GPIO_PM2,
-	GPIO_PM3,
-	GPIO_PM4,
-	GPIO_PM5,
-	GPIO_PM6,
-	GPIO_PM7,
-	GPIO_PN0,	/* pin 104 */
-	GPIO_PN1,
-	GPIO_PN2,
-	GPIO_PN3,
-	GPIO_PN4,
-	GPIO_PN5,
-	GPIO_PN6,
-	GPIO_PN7,
-	GPIO_PO0,	/* pin 112 */
-	GPIO_PO1,
-	GPIO_PO2,
-	GPIO_PO3,
-	GPIO_PO4,
-	GPIO_PO5,
-	GPIO_PO6,
-	GPIO_PO7,
-	GPIO_PP0,	/* pin 120 */
-	GPIO_PP1,
-	GPIO_PP2,
-	GPIO_PP3,
-	GPIO_PP4,
-	GPIO_PP5,
-	GPIO_PP6,
-	GPIO_PP7,
-	GPIO_PQ0,	/* pin 128 */
-	GPIO_PQ1,
-	GPIO_PQ2,
-	GPIO_PQ3,
-	GPIO_PQ4,
-	GPIO_PQ5,
-	GPIO_PQ6,
-	GPIO_PQ7,
-	GPIO_PR0,	/* pin 136 */
-	GPIO_PR1,
-	GPIO_PR2,
-	GPIO_PR3,
-	GPIO_PR4,
-	GPIO_PR5,
-	GPIO_PR6,
-	GPIO_PR7,
-	GPIO_PS0,	/* pin 144 */
-	GPIO_PS1,
-	GPIO_PS2,
-	GPIO_PS3,
-	GPIO_PS4,
-	GPIO_PS5,
-	GPIO_PS6,
-	GPIO_PS7,
-	GPIO_PT0,	/* pin 152 */
-	GPIO_PT1,
-	GPIO_PT2,
-	GPIO_PT3,
-	GPIO_PT4,
-	GPIO_PT5,
-	GPIO_PT6,
-	GPIO_PT7,
-	GPIO_PU0,	/* pin 160 */
-	GPIO_PU1,
-	GPIO_PU2,
-	GPIO_PU3,
-	GPIO_PU4,
-	GPIO_PU5,
-	GPIO_PU6,
-	GPIO_PU7,
-	GPIO_PV0,	/* pin 168 */
-	GPIO_PV1,
-	GPIO_PV2,
-	GPIO_PV3,
-	GPIO_PV4,
-	GPIO_PV5,
-	GPIO_PV6,
-	GPIO_PV7,
-	GPIO_PW0,	/* pin 176 */
-	GPIO_PW1,
-	GPIO_PW2,
-	GPIO_PW3,
-	GPIO_PW4,
-	GPIO_PW5,
-	GPIO_PW6,
-	GPIO_PW7,
-	GPIO_PX0,	/* pin 184 */
-	GPIO_PX1,
-	GPIO_PX2,
-	GPIO_PX3,
-	GPIO_PX4,
-	GPIO_PX5,
-	GPIO_PX6,
-	GPIO_PX7,
-	GPIO_PY0,	/* pin 192 */
-	GPIO_PY1,
-	GPIO_PY2,
-	GPIO_PY3,
-	GPIO_PY4,
-	GPIO_PY5,
-	GPIO_PY6,
-	GPIO_PY7,
-	GPIO_PZ0,	/* pin 200 */
-	GPIO_PZ1,
-	GPIO_PZ2,
-	GPIO_PZ3,
-	GPIO_PZ4,
-	GPIO_PZ5,
-	GPIO_PZ6,
-	GPIO_PZ7,
-	GPIO_PAA0,	/* pin 208 */
-	GPIO_PAA1,
-	GPIO_PAA2,
-	GPIO_PAA3,
-	GPIO_PAA4,
-	GPIO_PAA5,
-	GPIO_PAA6,
-	GPIO_PAA7,
-	GPIO_PBB0,	/* pin 216 */
-	GPIO_PBB1,
-	GPIO_PBB2,
-	GPIO_PBB3,
-	GPIO_PBB4,
-	GPIO_PBB5,
-	GPIO_PBB6,
-	GPIO_PBB7,
-	GPIO_PCC0,	/* pin 224 */
-	GPIO_PCC1,
-	GPIO_PCC2,
-	GPIO_PCC3,
-	GPIO_PCC4,
-	GPIO_PCC5,
-	GPIO_PCC6,
-	GPIO_PCC7,
-	GPIO_PDD0,	/* pin 232 */
-	GPIO_PDD1,
-	GPIO_PDD2,
-	GPIO_PDD3,
-	GPIO_PDD4,
-	GPIO_PDD5,
-	GPIO_PDD6,
-	GPIO_PDD7,
-	GPIO_PEE0,	/* pin 240 */
-	GPIO_PEE1,
-	GPIO_PEE2,
-	GPIO_PEE3,
-	GPIO_PEE4,
-	GPIO_PEE5,
-	GPIO_PEE6,
-	GPIO_PEE7,	/* pin 247 */
-};
-
 #endif	/* _TEGRA30_GPIO_H_ */
diff --git a/arch/arm/lib/lib1funcs.S b/arch/arm/lib/lib1funcs.S
index 9bf93ce..76968ce 100644
--- a/arch/arm/lib/lib1funcs.S
+++ b/arch/arm/lib/lib1funcs.S
@@ -367,9 +367,9 @@
 ENDPROC(Ldiv0)
 .popsection
 
-.pushsection .text.__gnu_thumb1_case_sqi, "ax"
 /* Thumb-1 specialities */
 #if defined(CONFIG_SYS_THUMB_BUILD) && !defined(CONFIG_HAS_THUMB2)
+.pushsection .text.__gnu_thumb1_case_sqi, "ax"
 ENTRY(__gnu_thumb1_case_sqi)
 	push	{r1}
 	mov	r1, lr
@@ -383,7 +383,7 @@
 ENDPROC(__gnu_thumb1_case_sqi)
 .popsection
 
-_.pushsection .text.__gnu_thumb1_case_uqi, "ax"
+.pushsection .text.__gnu_thumb1_case_uqi, "ax"
 ENTRY(__gnu_thumb1_case_uqi)
 	push	{r1}
 	mov	r1, lr
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index ba6983f..b18a12e 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -22,6 +22,7 @@
 	select SPL
 	select SUPPORT_SPL
 	select TEGRA_COMMON
+	select TEGRA_GPIO
 
 config TEGRA_ARMV8_COMMON
 	bool "Tegra 64-bit common options"
@@ -50,8 +51,14 @@
 
 config TEGRA210
 	bool "Tegra210 family"
+	select TEGRA_GPIO
 	select TEGRA_ARMV8_COMMON
 
+config TEGRA186
+	bool "Tegra186 family"
+	select TEGRA186_GPIO
+	select TEGRA_ARMV8_COMMON
+
 endchoice
 
 config TEGRA_DISCONNECT_UDC_ON_BOOT
@@ -75,5 +82,6 @@
 source "arch/arm/mach-tegra/tegra114/Kconfig"
 source "arch/arm/mach-tegra/tegra124/Kconfig"
 source "arch/arm/mach-tegra/tegra210/Kconfig"
+source "arch/arm/mach-tegra/tegra186/Kconfig"
 
 endif
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index b2dbc69..12ee1cd 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -7,6 +7,7 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
+ifndef CONFIG_TEGRA186
 ifdef CONFIG_SPL_BUILD
 obj-y += spl.o
 obj-y += cpu.o
@@ -30,9 +31,11 @@
 ifndef CONFIG_SPL_BUILD
 obj-$(CONFIG_ARMV7_PSCI) += psci.o
 endif
+endif
 
 obj-$(CONFIG_TEGRA20) += tegra20/
 obj-$(CONFIG_TEGRA30) += tegra30/
 obj-$(CONFIG_TEGRA114) += tegra114/
 obj-$(CONFIG_TEGRA124) += tegra124/
+obj-$(CONFIG_TEGRA186) += tegra186/
 obj-$(CONFIG_TEGRA210) += tegra210/
diff --git a/arch/arm/mach-tegra/board186.c b/arch/arm/mach-tegra/board186.c
new file mode 100644
index 0000000..f4b6152
--- /dev/null
+++ b/arch/arm/mach-tegra/board186.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2016, NVIDIA CORPORATION.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/arch/tegra.h>
+#include <asm/arch-tegra/mmc.h>
+#include <asm/arch-tegra/tegra_mmc.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int dram_init(void)
+{
+	gd->ram_size = (1.5 * 1024 * 1024 * 1024);
+	return 0;
+}
+
+int board_early_init_f(void)
+{
+	return 0;
+}
+
+int board_init(void)
+{
+	return 0;
+}
+
+int board_late_init(void)
+{
+	return 0;
+}
+
+void dram_init_banksize(void)
+{
+	gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
+	gd->bd->bi_dram[0].size = gd->ram_size;
+}
+
+void pad_init_mmc(struct mmc_host *host)
+{
+}
+
+int board_mmc_init(bd_t *bd)
+{
+	tegra_mmc_init();
+
+	return 0;
+}
+
+int ft_system_setup(void *blob, bd_t *bd)
+{
+	return 0;
+}
diff --git a/arch/arm/mach-tegra/tegra186/Kconfig b/arch/arm/mach-tegra/tegra186/Kconfig
new file mode 100644
index 0000000..97cf23f
--- /dev/null
+++ b/arch/arm/mach-tegra/tegra186/Kconfig
@@ -0,0 +1,25 @@
+# Copyright (c) 2016, NVIDIA CORPORATION.
+#
+# SPDX-License-Identifier: GPL-2.0
+
+if TEGRA186
+
+choice
+	prompt "Tegra186 board select"
+
+config TARGET_P2771_0000
+	bool "NVIDIA Tegra186 P2771-0000 board"
+	help
+	  P2771-0000 is a P3310 CPU board married to a P2597 I/O board. The
+	  combination contains SoC, DRAM, eMMC, SD card slot, HDMI, USB
+	  micro-B port, Ethernet, USB3 host port, SATA, PCIe, and two GPIO
+	  expansion headers.
+
+endchoice
+
+config SYS_SOC
+	default "tegra186"
+
+source "board/nvidia/p2771-0000/Kconfig"
+
+endif
diff --git a/arch/arm/mach-tegra/tegra186/Makefile b/arch/arm/mach-tegra/tegra186/Makefile
new file mode 100644
index 0000000..ce4610d
--- /dev/null
+++ b/arch/arm/mach-tegra/tegra186/Makefile
@@ -0,0 +1,8 @@
+# Copyright (c) 2016, NVIDIA CORPORATION.
+#
+# SPDX-License-Identifier: GPL-2.0
+
+obj-y += ../arm64-mmu.o
+obj-y += ../board186.o
+obj-y += ../lowlevel_init.o
+obj-$(CONFIG_DISPLAY_CPUINFO) += ../sys_info.o
diff --git a/arch/microblaze/include/asm/asm.h b/arch/microblaze/include/asm/asm.h
index 11f3dd0..94f0562 100644
--- a/arch/microblaze/include/asm/asm.h
+++ b/arch/microblaze/include/asm/asm.h
@@ -50,7 +50,7 @@
 #define NOP	__asm__ __volatile__ ("nop");
 
 /* use machine status registe USE_MSR_REG */
-#if XILINX_USE_MSR_INSTR == 1
+#if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR == 1
 #define MSRSET(val) \
 	__asm__ __volatile__ ("msrset r0," #val );
 
diff --git a/arch/powerpc/cpu/mpc512x/fixed_sdram.c b/arch/powerpc/cpu/mpc512x/fixed_sdram.c
index 6451ea9..68c5f8a 100644
--- a/arch/powerpc/cpu/mpc512x/fixed_sdram.c
+++ b/arch/powerpc/cpu/mpc512x/fixed_sdram.c
@@ -70,7 +70,7 @@
 		mddrc_config = &default_mddrc_config;
 	if (dram_init_seq == NULL) {
 		dram_init_seq = default_init_seq;
-		seq_sz = sizeof(default_init_seq)/sizeof(u32);
+		seq_sz = ARRAY_SIZE(default_init_seq);
 	}
 
 	/* Initialize IO Control */
diff --git a/arch/powerpc/cpu/mpc8260/cpu_init.c b/arch/powerpc/cpu/mpc8260/cpu_init.c
index a9bb5ad..55130f7 100644
--- a/arch/powerpc/cpu/mpc8260/cpu_init.c
+++ b/arch/powerpc/cpu/mpc8260/cpu_init.c
@@ -253,7 +253,7 @@
 		RSR_ESRS, "External Soft"}, {
 		RSR_EHRS, "External Hard"}
 	};
-	static int n = sizeof bits / sizeof bits[0];
+	static int n = ARRAY_SIZE(bits);
 	ulong rsr = gd->arch.reset_status;
 	int i;
 	char *sep;
diff --git a/arch/powerpc/cpu/mpc8260/ether_fcc.c b/arch/powerpc/cpu/mpc8260/ether_fcc.c
index 9bb395e..a11ad1e 100644
--- a/arch/powerpc/cpu/mpc8260/ether_fcc.c
+++ b/arch/powerpc/cpu/mpc8260/ether_fcc.c
@@ -362,7 +362,7 @@
 	struct eth_device* dev;
 	int i;
 
-	for (i = 0; i < sizeof(ether_fcc_info) / sizeof(ether_fcc_info[0]); i++)
+	for (i = 0; i < ARRAY_SIZE(ether_fcc_info); i++)
 	{
 		dev = (struct eth_device*) malloc(sizeof *dev);
 		memset(dev, 0, sizeof *dev);
@@ -432,7 +432,7 @@
 	{ offsetof(elbt_rxeacc, badlen),	"Bad Frame Length"	},
 	{ offsetof(elbt_rxeacc, badbit),	"Data Compare Errors"	},
 };
-static int rxeacc_ndesc = sizeof (rxeacc_descs) / sizeof (rxeacc_descs[0]);
+static int rxeacc_ndesc = ARRAY_SIZE(rxeacc_descs);
 
 typedef
 	struct {
@@ -449,7 +449,7 @@
 	{ offsetof(elbt_txeacc, un),		"Underrun"		},
 	{ offsetof(elbt_txeacc, csl),		"Carrier Sense Lost"	},
 };
-static int txeacc_ndesc = sizeof (txeacc_descs) / sizeof (txeacc_descs[0]);
+static int txeacc_ndesc = ARRAY_SIZE(txeacc_descs);
 
 typedef
 	struct {
@@ -500,7 +500,7 @@
 	{ offsetof(fcc_enet_t, fen_p512c),	"512-1023 Octet Frames"	},
 	{ offsetof(fcc_enet_t, fen_p1024c),	"1024-1518 Octet Frames"},
 };
-static int epram_ndesc = sizeof (epram_descs) / sizeof (epram_descs[0]);
+static int epram_ndesc = ARRAY_SIZE(epram_descs);
 
 /*
  * given an elbt_prdesc array and an array of base addresses, print
diff --git a/arch/powerpc/cpu/mpc83xx/cpu_init.c b/arch/powerpc/cpu/mpc83xx/cpu_init.c
index 0791043..f911275 100644
--- a/arch/powerpc/cpu/mpc83xx/cpu_init.c
+++ b/arch/powerpc/cpu/mpc83xx/cpu_init.c
@@ -484,7 +484,7 @@
 		RSR_SRS,  "External/Internal Soft"}, {
 		RSR_HRS,  "External/Internal Hard"}
 	};
-	static int n = sizeof bits / sizeof bits[0];
+	static int n = ARRAY_SIZE(bits);
 	ulong rsr = gd->arch.reset_status;
 	int i;
 	char *sep;
diff --git a/arch/powerpc/cpu/mpc83xx/speed.c b/arch/powerpc/cpu/mpc83xx/speed.c
index 2e91f51..5498c19 100644
--- a/arch/powerpc/cpu/mpc83xx/speed.c
+++ b/arch/powerpc/cpu/mpc83xx/speed.c
@@ -412,7 +412,7 @@
 #endif
 
 	corecnf_tab_index = ((corepll & 0x1F) << 2) | ((corepll & 0x60) >> 5);
-	if (corecnf_tab_index > (sizeof(corecnf_tab) / sizeof(corecnf_t))) {
+	if (corecnf_tab_index > (ARRAY_SIZE(corecnf_tab))) {
 		/* corecnf_tab_index is too high, possibly wrong value */
 		return -11;
 	}
diff --git a/arch/powerpc/cpu/mpc85xx/ether_fcc.c b/arch/powerpc/cpu/mpc85xx/ether_fcc.c
index 14358ae..51f1bee 100644
--- a/arch/powerpc/cpu/mpc85xx/ether_fcc.c
+++ b/arch/powerpc/cpu/mpc85xx/ether_fcc.c
@@ -424,7 +424,7 @@
 	struct eth_device* dev;
 	int i;
 
-	for (i = 0; i < sizeof(ether_fcc_info) / sizeof(ether_fcc_info[0]); i++)
+	for (i = 0; i < ARRAY_SIZE(ether_fcc_info); i++)
 	{
 		dev = (struct eth_device*) malloc(sizeof *dev);
 		memset(dev, 0, sizeof *dev);
diff --git a/arch/powerpc/cpu/mpc8xx/fec.c b/arch/powerpc/cpu/mpc8xx/fec.c
index ea4ab3a..f1ae358 100644
--- a/arch/powerpc/cpu/mpc8xx/fec.c
+++ b/arch/powerpc/cpu/mpc8xx/fec.c
@@ -137,7 +137,7 @@
 	struct ether_fcc_info_s *efis;
 	int             i;
 
-	for (i = 0; i < sizeof(ether_fcc_info) / sizeof(ether_fcc_info[0]); i++) {
+	for (i = 0; i < ARRAY_SIZE(ether_fcc_info); i++) {
 
 		dev = malloc(sizeof(*dev));
 		if (dev == NULL)
@@ -879,7 +879,7 @@
 
 	/* Setup the pin configuration of the FEC(s)
 	*/
-	for (i = 0; i < sizeof(ether_fcc_info) / sizeof(ether_fcc_info[0]); i++)
+	for (i = 0; i < ARRAY_SIZE(ether_fcc_info); i++)
 		fec_pin_init(ether_fcc_info[i].ether_index);
 }
 
diff --git a/arch/powerpc/cpu/ppc4xx/reginfo.c b/arch/powerpc/cpu/ppc4xx/reginfo.c
index 339d38a..a42327e 100644
--- a/arch/powerpc/cpu/ppc4xx/reginfo.c
+++ b/arch/powerpc/cpu/ppc4xx/reginfo.c
@@ -321,7 +321,7 @@
 	PRINT_DCR(OPB2PLB40_BCTRL);
 	PRINT_DCR(P4P3BO0_CFG);
 #endif
-	n = sizeof(ppc4xx_reg) / sizeof(ppc4xx_reg[0]);
+	n = ARRAY_SIZE(ppc4xx_reg);
 	for (i = 0; i < n; i++) {
 		value = 0;
 		type = ppc4xx_reg[i].type;
diff --git a/arch/powerpc/cpu/ppc4xx/sdram.c b/arch/powerpc/cpu/ppc4xx/sdram.c
index d4ef36d..cd63456 100644
--- a/arch/powerpc/cpu/ppc4xx/sdram.c
+++ b/arch/powerpc/cpu/ppc4xx/sdram.c
@@ -33,7 +33,7 @@
 sdram_conf_t mb0cf[] = CONFIG_SYS_SDRAM_TABLE;
 #endif
 
-#define N_MB0CF (sizeof(mb0cf) / sizeof(mb0cf[0]))
+#define N_MB0CF (ARRAY_SIZE(mb0cf))
 
 #ifdef CONFIG_SYS_SDRAM_CASL
 static ulong ns2clks(ulong ns)
@@ -266,7 +266,7 @@
 #define CONFIG_SYS_SDRAM0_CFG0		0x82000000 /* DCEN=1, PMUD=0, 64-bit */
 #endif
 
-#define N_MB0CF (sizeof(mb0cf) / sizeof(mb0cf[0]))
+#define N_MB0CF (ARRAY_SIZE(mb0cf))
 
 #define NUM_TRIES 64
 #define NUM_READS 10
diff --git a/arch/powerpc/include/asm/arch-mpc85xx/gpio.h b/arch/powerpc/include/asm/arch-mpc85xx/gpio.h
index da7352a..41b6677 100644
--- a/arch/powerpc/include/asm/arch-mpc85xx/gpio.h
+++ b/arch/powerpc/include/asm/arch-mpc85xx/gpio.h
@@ -14,6 +14,8 @@
 #ifndef __ASM_ARCH_MX85XX_GPIO_H
 #define __ASM_ARCH_MX85XX_GPIO_H
 
+#ifndef CONFIG_MPC85XX_GPIO
 #include <asm/mpc85xx_gpio.h>
+#endif
 
 #endif
diff --git a/arch/powerpc/include/asm/immap_85xx.h b/arch/powerpc/include/asm/immap_85xx.h
index 07d2adf..c045a24 100644
--- a/arch/powerpc/include/asm/immap_85xx.h
+++ b/arch/powerpc/include/asm/immap_85xx.h
@@ -265,6 +265,7 @@
 #define PIWAR_WRITE_SNOOP	0x00005000
 #define PIWAR_MEM_2G		0x0000001e
 
+#ifndef CONFIG_MPC85XX_GPIO
 typedef struct ccsr_gpio {
 	u32	gpdir;
 	u32	gpodr;
@@ -273,6 +274,7 @@
 	u32	gpimr;
 	u32	gpicr;
 } ccsr_gpio_t;
+#endif
 
 /* L2 Cache Registers */
 typedef struct ccsr_l2cache {
diff --git a/arch/sandbox/include/asm/gpio.h b/arch/sandbox/include/asm/gpio.h
index 8317db1..427af2c 100644
--- a/arch/sandbox/include/asm/gpio.h
+++ b/arch/sandbox/include/asm/gpio.h
@@ -41,6 +41,26 @@
 int sandbox_gpio_set_value(struct udevice *dev, unsigned int offset, int value);
 
 /**
+ * Set or reset the simulated open drain mode of a GPIO (used only in sandbox
+ * test code)
+ *
+ * @param gp	GPIO number
+ * @param value	value to set (0 for enabled open drain mode, non-zero for
+ * 		disabled)
+ * @return -1 on error, 0 if ok
+ */
+int sandbox_gpio_set_open_drain(struct udevice *dev, unsigned offset, int value);
+
+/**
+ * Return the state of the simulated open drain mode of a GPIO (used only in
+ * sandbox test code)
+ *
+ * @param gp	GPIO number
+ * @return -1 on error, 0 if GPIO is input, >0 if output
+ */
+int sandbox_gpio_get_open_drain(struct udevice *dev, unsigned offset);
+
+/**
  * Return the simulated direction of a GPIO (used only in sandbox test code)
  *
  * @param gp	GPIO number
diff --git a/board/BuR/common/common.c b/board/BuR/common/common.c
index ce4acc1..e947e54 100644
--- a/board/BuR/common/common.c
+++ b/board/BuR/common/common.c
@@ -259,7 +259,7 @@
 	}
 #ifdef CONFIG_NAND
 	dtbsize = 0x20000;
-	rc = nand_read_skip_bad(&nand_info[0], 0x40000, (size_t *)&dtbsize,
+	rc = nand_read_skip_bad(nand_info[0], 0x40000, (size_t *)&dtbsize,
 				NULL, 0x20000, (u_char *)dtbaddr);
 #else
 	char *dtbname = getenv("dtb");
diff --git a/board/atmel/at91sam9261ek/at91sam9261ek.c b/board/atmel/at91sam9261ek/at91sam9261ek.c
index 7b7cd2c..6398bcb 100644
--- a/board/atmel/at91sam9261ek/at91sam9261ek.c
+++ b/board/atmel/at91sam9261ek/at91sam9261ek.c
@@ -212,7 +212,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 += nand_info[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 af68e10..04e5812 100644
--- a/board/atmel/at91sam9263ek/at91sam9263ek.c
+++ b/board/atmel/at91sam9263ek/at91sam9263ek.c
@@ -191,7 +191,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 += nand_info[i]->size;
 #ifndef CONFIG_SYS_NO_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 4c64312..6871916 100644
--- a/board/atmel/at91sam9m10g45ek/at91sam9m10g45ek.c
+++ b/board/atmel/at91sam9m10g45ek/at91sam9m10g45ek.c
@@ -272,7 +272,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 += nand_info[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 d3555bb..fc4f50d 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 += nand_info[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 9ef2864..994f246 100644
--- a/board/atmel/at91sam9rlek/at91sam9rlek.c
+++ b/board/atmel/at91sam9rlek/at91sam9rlek.c
@@ -151,7 +151,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 += nand_info[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 c14df30..b0d440d 100644
--- a/board/atmel/at91sam9x5ek/at91sam9x5ek.c
+++ b/board/atmel/at91sam9x5ek/at91sam9x5ek.c
@@ -196,7 +196,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 += nand_info[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 e8ee612..fa90270 100644
--- a/board/atmel/sama5d3xek/sama5d3xek.c
+++ b/board/atmel/sama5d3xek/sama5d3xek.c
@@ -207,7 +207,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 += nand_info[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 f4eef96..23ec274 100644
--- a/board/atmel/sama5d4_xplained/sama5d4_xplained.c
+++ b/board/atmel/sama5d4_xplained/sama5d4_xplained.c
@@ -191,7 +191,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 += nand_info[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 aee6217..72bad23 100644
--- a/board/atmel/sama5d4ek/sama5d4ek.c
+++ b/board/atmel/sama5d4ek/sama5d4ek.c
@@ -187,7 +187,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 += nand_info[i]->size;
 #endif
 	lcd_printf("%ld MB SDRAM, %ld MB NAND\n",
 		   dram_size >> 20, nand_size >> 20);
diff --git a/board/avionic-design/common/tamonten-ng.c b/board/avionic-design/common/tamonten-ng.c
index 1704627..106be9b 100644
--- a/board/avionic-design/common/tamonten-ng.c
+++ b/board/avionic-design/common/tamonten-ng.c
@@ -42,12 +42,12 @@
 void gpio_early_init(void)
 {
 	/* Turn on the alive signal */
-	gpio_request(GPIO_PV2, "ALIVE");
-	gpio_direction_output(GPIO_PV2, 1);
+	gpio_request(TEGRA_GPIO(V, 2), "ALIVE");
+	gpio_direction_output(TEGRA_GPIO(V, 2), 1);
 
 	/* Remove the reset on the external periph */
-	gpio_request(GPIO_PI4, "nRST_PERIPH");
-	gpio_direction_output(GPIO_PI4, 1);
+	gpio_request(TEGRA_GPIO(I, 4), "nRST_PERIPH");
+	gpio_direction_output(TEGRA_GPIO(I, 4), 1);
 }
 
 void pmu_write(uchar reg, uchar data)
@@ -73,8 +73,8 @@
 	pmu_write(PMU_REG_LDO5, PMU_LDO5(HIGH_POWER, 3300));
 
 	/* Switch the power on */
-	gpio_request(GPIO_PJ2, "EN_3V3_EMMC");
-	gpio_direction_output(GPIO_PJ2, 1);
+	gpio_request(TEGRA_GPIO(J, 2), "EN_3V3_EMMC");
+	gpio_direction_output(TEGRA_GPIO(J, 2), 1);
 }
 
 /*
diff --git a/board/avionic-design/common/tamonten.c b/board/avionic-design/common/tamonten.c
index 9c86779..4fb36a2 100644
--- a/board/avionic-design/common/tamonten.c
+++ b/board/avionic-design/common/tamonten.c
@@ -23,8 +23,8 @@
 #ifdef CONFIG_BOARD_EARLY_INIT_F
 void gpio_early_init(void)
 {
-	gpio_request(GPIO_PI4, NULL);
-	gpio_direction_output(GPIO_PI4, 1);
+	gpio_request(TEGRA_GPIO(I, 4), NULL);
+	gpio_direction_output(TEGRA_GPIO(I, 4), 1);
 }
 #endif
 
diff --git a/board/esd/common/esd405ep_nand.c b/board/esd/common/esd405ep_nand.c
index f46936c..51ac10c 100644
--- a/board/esd/common/esd405ep_nand.c
+++ b/board/esd/common/esd405ep_nand.c
@@ -16,7 +16,7 @@
  */
 static void esd405ep_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 {
-	struct nand_chip *this = mtd->priv;
+	struct nand_chip *this = mtd_to_nand(mtd);
 	if (ctrl & NAND_CTRL_CHANGE) {
 		if ( ctrl & NAND_CLE )
 			out_be32((void *)GPIO0_OR, in_be32((void *)GPIO0_OR) | CONFIG_SYS_NAND_CLE);
diff --git a/board/freescale/b4860qds/Makefile b/board/freescale/b4860qds/Makefile
index 0acd2a9..673d2ea 100644
--- a/board/freescale/b4860qds/Makefile
+++ b/board/freescale/b4860qds/Makefile
@@ -5,11 +5,11 @@
 #
 
 ifdef CONFIG_SPL_BUILD
-obj-y += spl.o
+obj-y	+= spl.o
 else
 obj-y	+= b4860qds.o
-obj-$(CONFIG_B4860QDS)+= eth_b4860qds.o
-obj-$(CONFIG_PCI)      += pci.o
+obj-$(CONFIG_B4860QDS)	+= eth_b4860qds.o
+obj-$(CONFIG_PCI)	+= pci.o
 endif
 
 obj-y	+= ddr.o
diff --git a/board/freescale/b4860qds/ddr.c b/board/freescale/b4860qds/ddr.c
index eb10a6f..31b186e 100644
--- a/board/freescale/b4860qds/ddr.c
+++ b/board/freescale/b4860qds/ddr.c
@@ -179,15 +179,13 @@
 
 #if defined(CONFIG_SPL_BUILD) || !defined(CONFIG_RAMBOOT_PBL)
 	puts("Initializing....using SPD\n");
-
 	dram_size = fsl_ddr_sdram();
-
-	dram_size = setup_ddr_tlbs(dram_size / 0x100000);
-	dram_size *= 0x100000;
-
 #else
 	dram_size =  fsl_ddr_sdram_size();
 #endif
+	dram_size = setup_ddr_tlbs(dram_size / 0x100000);
+	dram_size *= 0x100000;
+
 	return dram_size;
 }
 
diff --git a/board/freescale/b4860qds/spl.c b/board/freescale/b4860qds/spl.c
index 3f7cc03..fabc783 100644
--- a/board/freescale/b4860qds/spl.c
+++ b/board/freescale/b4860qds/spl.c
@@ -91,6 +91,7 @@
 	get_clocks();
 	mem_malloc_init(CONFIG_SPL_RELOC_MALLOC_ADDR,
 			CONFIG_SPL_RELOC_MALLOC_SIZE);
+	gd->flags |= GD_FLG_FULL_MALLOC_INIT;
 
 #ifndef CONFIG_SPL_NAND_BOOT
 	env_init();
diff --git a/board/freescale/bsc9131rdb/Makefile b/board/freescale/bsc9131rdb/Makefile
index b26d3a1..8027750 100644
--- a/board/freescale/bsc9131rdb/Makefile
+++ b/board/freescale/bsc9131rdb/Makefile
@@ -13,15 +13,11 @@
 endif
 
 ifdef MINIMAL
-
-obj-y	+= spl_minimal.o tlb.o law.o
-
+obj-y	+= spl_minimal.o
 else
-
-obj-y        += bsc9131rdb.o
-obj-y        += ddr.o
-obj-y        += law.o
-obj-y        += tlb.o
-#obj-y		+= bsc9131rdb_mux.o
-
+obj-y	+= bsc9131rdb.o
+obj-y	+= ddr.o
 endif
+
+obj-y	+= law.o
+obj-y	+= tlb.o
diff --git a/board/freescale/bsc9132qds/Makefile b/board/freescale/bsc9132qds/Makefile
index 2e4170f..5419335 100644
--- a/board/freescale/bsc9132qds/Makefile
+++ b/board/freescale/bsc9132qds/Makefile
@@ -13,14 +13,11 @@
 endif
 
 ifdef MINIMAL
-
-obj-y	+= spl_minimal.o tlb.o law.o
-
+obj-y	+= spl_minimal.o
 else
-
 obj-y	+= bsc9132qds.o
 obj-y	+= ddr.o
+endif
+
 obj-y	+= law.o
 obj-y	+= tlb.o
-
-endif
diff --git a/board/freescale/c29xpcie/Makefile b/board/freescale/c29xpcie/Makefile
index 818484a..93b3cba 100644
--- a/board/freescale/c29xpcie/Makefile
+++ b/board/freescale/c29xpcie/Makefile
@@ -11,15 +11,15 @@
 endif
 
 ifdef MINIMAL
-obj-y	+= spl_minimal.o tlb.o law.o
+obj-y	+= spl_minimal.o
 else
 ifdef CONFIG_SPL_BUILD
 obj-y	+= spl.o
 endif
-
 obj-y	+= c29xpcie.o
 obj-y	+= cpld.o
 obj-y	+= ddr.o
+endif
+
 obj-y	+= law.o
 obj-y	+= tlb.o
-endif
diff --git a/board/freescale/c29xpcie/spl.c b/board/freescale/c29xpcie/spl.c
index 3d31d41..d8d73c7 100644
--- a/board/freescale/c29xpcie/spl.c
+++ b/board/freescale/c29xpcie/spl.c
@@ -57,6 +57,7 @@
 	get_clocks();
 	mem_malloc_init(CONFIG_SPL_RELOC_MALLOC_ADDR,
 			CONFIG_SPL_RELOC_MALLOC_SIZE);
+	gd->flags |= GD_FLG_FULL_MALLOC_INIT;
 
 	/* relocate environment function pointers etc. */
 	nand_spl_load_image(CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE,
diff --git a/board/freescale/common/ls102xa_stream_id.c b/board/freescale/common/ls102xa_stream_id.c
index 3d5404e..0abaffb 100644
--- a/board/freescale/common/ls102xa_stream_id.c
+++ b/board/freescale/common/ls102xa_stream_id.c
@@ -12,9 +12,12 @@
 {
 	void *scfg = (void *)CONFIG_SYS_FSL_SCFG_ADDR;
 	int i;
+	u32 icid;
 
-	for (i = 0; i < num; i++)
-		out_be32((u32 *)(scfg + id[i].offset), id[i].stream_id);
+	for (i = 0; i < num; i++) {
+		icid = (id[i].stream_id & 0xff) << 24;
+		out_be32((u32 *)(scfg + id[i].offset), icid);
+	}
 }
 
 void ls1021x_config_caam_stream_id(struct liodn_id_table *tbl, int size)
diff --git a/board/freescale/common/qixis.c b/board/freescale/common/qixis.c
index 113295f..0db0ed6 100644
--- a/board/freescale/common/qixis.c
+++ b/board/freescale/common/qixis.c
@@ -14,6 +14,13 @@
 #include <i2c.h>
 #include "qixis.h"
 
+#ifndef QIXIS_LBMAP_BRDCFG_REG
+/*
+ * For consistency with existing platforms
+ */
+#define QIXIS_LBMAP_BRDCFG_REG 0x00
+#endif
+
 #ifdef CONFIG_SYS_I2C_FPGA_ADDR
 u8 qixis_read_i2c(unsigned int reg)
 {
@@ -27,6 +34,7 @@
 }
 #endif
 
+#ifdef QIXIS_BASE
 u8 qixis_read(unsigned int reg)
 {
 	void *p = (void *)QIXIS_BASE;
@@ -40,6 +48,7 @@
 
 	out_8(p + reg, value);
 }
+#endif
 
 u16 qixis_read_minor(void)
 {
@@ -142,9 +151,9 @@
 {
 	u8 reg;
 
-	reg = QIXIS_READ(brdcfg[0]);
+	reg = QIXIS_READ(brdcfg[QIXIS_LBMAP_BRDCFG_REG]);
 	reg = (reg & ~QIXIS_LBMAP_MASK) | lbmap;
-	QIXIS_WRITE(brdcfg[0], reg);
+	QIXIS_WRITE(brdcfg[QIXIS_LBMAP_BRDCFG_REG], reg);
 }
 
 static void __maybe_unused set_rcw_src(int rcw_src)
diff --git a/board/freescale/ls1012afrdm/Kconfig b/board/freescale/ls1012afrdm/Kconfig
new file mode 100644
index 0000000..a34521c
--- /dev/null
+++ b/board/freescale/ls1012afrdm/Kconfig
@@ -0,0 +1,15 @@
+if TARGET_LS1012AFRDM
+
+config SYS_BOARD
+	default "ls1012afrdm"
+
+config SYS_VENDOR
+	default "freescale"
+
+config SYS_SOC
+	default "fsl-layerscape"
+
+config SYS_CONFIG_NAME
+	default "ls1012afrdm"
+
+endif
diff --git a/board/freescale/ls1012afrdm/MAINTAINERS b/board/freescale/ls1012afrdm/MAINTAINERS
new file mode 100644
index 0000000..842f86f
--- /dev/null
+++ b/board/freescale/ls1012afrdm/MAINTAINERS
@@ -0,0 +1,6 @@
+LS1012AFRDM BOARD
+M:	Prabhakar Kushwaha <prabhakar.kushwaha@nxp.com>
+S:	Maintained
+F:	board/freescale/ls1012afrdm/
+F:	include/configs/ls1012afrdm.h
+F:	configs/ls1012afrdm_qspi_defconfig
diff --git a/board/freescale/ls1012afrdm/Makefile b/board/freescale/ls1012afrdm/Makefile
new file mode 100644
index 0000000..dbfa2ce
--- /dev/null
+++ b/board/freescale/ls1012afrdm/Makefile
@@ -0,0 +1,7 @@
+#
+# Copyright 2016 Freescale Semiconductor, Inc.
+#
+# SPDX-License-Identifier:      GPL-2.0+
+#
+
+obj-y += ls1012afrdm.o
diff --git a/board/freescale/ls1012afrdm/README b/board/freescale/ls1012afrdm/README
new file mode 100644
index 0000000..181c461
--- /dev/null
+++ b/board/freescale/ls1012afrdm/README
@@ -0,0 +1,58 @@
+Overview
+--------
+QorIQ LS1012A FREEDOM (LS1012AFRDM) is a high-performance development
+platform, with a complete debugging environment. The LS1012AFRDM board
+supports the QorIQ LS1012A processor and is optimized to support the
+high-bandwidth DDR3L memory and a full complement of high-speed SerDes ports.
+
+LS1012A SoC Overview
+--------------------
+Please refer arch/arm/cpu/armv8/fsl-layerscape/doc/README.soc for LS2080A
+SoC overview.
+
+ LS1012AFRDM board Overview
+ -----------------------
+ - SERDES Connections, 2 lanes supportingspeeds upto 1 Gbit/s
+     - 2 SGMII 1G PHYs
+ - DDR Controller
+     - 4 Gb DDR3L SDRAM memory, running at data rates up to 1 GT/s
+	operating at 1.35 V
+ - QSPI
+     - Onboard 512 Mbit QSPI flash memory running at speed up
+      to 108/54 MHz
+ - One high-speed USB 2.0/3.0 port, one USB 2.0 port
+     - USB 2.0/3.0 port is configured as On-The-Go (OTG) with a
+       Micro-AB connector.
+     - USB 2.0 port is a debug port (CMSIS DAP) and is configured
+       as a Micro-AB device.
+ - I2C controller
+     - One I2C bus with connectivity to Arduino headers
+ - UART
+     - UART (Console): UART1 (Without flow control) for console
+ - ARM JTAG support
+     - ARM Cortex® 10-pin JTAG connector for LS1012A
+     - CMSIS DAP through K20 microcontroller
+ - SAI Audio interface
+     - One SAI port, SAI 2 with full duplex support
+ - Clocks
+     - 25 MHz crystal for LS1012A
+     - 8 MHz Crystal for K20
+     - 24 MHz for SC16IS740IPW SPI to Dual UART bridge
+ - Power Supplies
+     - 5 V input supply from USB
+     - 0.9 V, 1.35 V, and 1.8 V for VDD/Core, DDR, I/O, and
+       other board interfaces
+
+Booting Options
+---------------
+QSPI Flash 1
+
+QSPI flash map
+--------------
+Images		| Size	|QSPI Flash Address
+------------------------------------------
+RCW + PBI	| 1MB	| 0x4000_0000
+U-boot 		| 1MB	| 0x4010_0000
+U-boot Env 	| 1MB	| 0x4020_0000
+PPA FIT image	| 2MB	| 0x4050_0000
+Linux ITB	| ~53MB | 0x40A0_0000
diff --git a/board/freescale/ls1012afrdm/ls1012afrdm.c b/board/freescale/ls1012afrdm/ls1012afrdm.c
new file mode 100644
index 0000000..a94a458
--- /dev/null
+++ b/board/freescale/ls1012afrdm/ls1012afrdm.c
@@ -0,0 +1,192 @@
+/*
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/fsl_serdes.h>
+#include <asm/arch/soc.h>
+#include <hwconfig.h>
+#include <fsl_csu.h>
+#include <environment.h>
+#include <fsl_mmdc.h>
+#include <netdev.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static void set_wait_for_bits_clear(void *ptr, u32 value, u32 bits)
+{
+	int timeout = 1000;
+
+	out_be32(ptr, value);
+
+	while (in_be32(ptr) & bits) {
+		udelay(100);
+		timeout--;
+	}
+	if (timeout <= 0)
+		puts("Error: wait for clear timeout.\n");
+}
+
+int checkboard(void)
+{
+	puts("Board: LS1012AFRDM ");
+
+	return 0;
+}
+
+void mmdc_init(void)
+{
+	struct mmdc_p_regs *mmdc =
+		(struct mmdc_p_regs *)CONFIG_SYS_FSL_DDR_ADDR;
+
+	out_be32(&mmdc->mdscr, CONFIGURATION_REQ);
+
+	/* configure timing parms */
+	out_be32(&mmdc->mdotc,  CONFIG_SYS_MMDC_CORE_ODT_TIMING);
+	out_be32(&mmdc->mdcfg0, CONFIG_SYS_MMDC_CORE_TIMING_CFG_0);
+	out_be32(&mmdc->mdcfg1, CONFIG_SYS_MMDC_CORE_TIMING_CFG_1);
+	out_be32(&mmdc->mdcfg2, CONFIG_SYS_MMDC_CORE_TIMING_CFG_2);
+
+	/* other parms	*/
+	out_be32(&mmdc->mdmisc,    CONFIG_SYS_MMDC_CORE_MISC);
+	out_be32(&mmdc->mpmur0,    CONFIG_SYS_MMDC_PHY_MEASURE_UNIT);
+	out_be32(&mmdc->mdrwd,     CONFIG_SYS_MMDC_CORE_RDWR_CMD_DELAY);
+	out_be32(&mmdc->mpodtctrl, CONFIG_SYS_MMDC_PHY_ODT_CTRL);
+
+	/* out of reset delays */
+	out_be32(&mmdc->mdor,  CONFIG_SYS_MMDC_CORE_OUT_OF_RESET_DELAY);
+
+	/* physical parms */
+	out_be32(&mmdc->mdctl, CONFIG_SYS_MMDC_CORE_CONTROL_1);
+	out_be32(&mmdc->mdasp, CONFIG_SYS_MMDC_CORE_ADDR_PARTITION);
+
+       /* Enable MMDC */
+	out_be32(&mmdc->mdctl, CONFIG_SYS_MMDC_CORE_CONTROL_2);
+
+	/* dram init sequence: update MRs */
+	out_be32(&mmdc->mdscr, (CMD_ADDR_LSB_MR_ADDR(0x8) | CONFIGURATION_REQ |
+				CMD_LOAD_MODE_REG | CMD_BANK_ADDR_2));
+	out_be32(&mmdc->mdscr, (CONFIGURATION_REQ | CMD_LOAD_MODE_REG |
+				CMD_BANK_ADDR_3));
+	out_be32(&mmdc->mdscr, (CMD_ADDR_LSB_MR_ADDR(0x4) | CONFIGURATION_REQ |
+				CMD_LOAD_MODE_REG | CMD_BANK_ADDR_1));
+	out_be32(&mmdc->mdscr, (CMD_ADDR_MSB_MR_OP(0x19) |
+				CMD_ADDR_LSB_MR_ADDR(0x30) | CONFIGURATION_REQ |
+				CMD_LOAD_MODE_REG | CMD_BANK_ADDR_0));
+
+       /* dram init sequence: ZQCL */
+	out_be32(&mmdc->mdscr, (CMD_ADDR_MSB_MR_OP(0x4) | CONFIGURATION_REQ |
+				CMD_ZQ_CALIBRATION | CMD_BANK_ADDR_0));
+	set_wait_for_bits_clear(&mmdc->mpzqhwctrl,
+				CONFIG_SYS_MMDC_PHY_ZQ_HW_CTRL,
+				FORCE_ZQ_AUTO_CALIBRATION);
+
+       /* Calibrations now: wr lvl */
+	out_be32(&mmdc->mdscr, (CMD_ADDR_LSB_MR_ADDR(0x84) |
+				CONFIGURATION_REQ | CMD_LOAD_MODE_REG |
+				CMD_BANK_ADDR_1));
+	out_be32(&mmdc->mdscr, (CONFIGURATION_REQ | WL_EN | CMD_NORMAL));
+	set_wait_for_bits_clear(&mmdc->mpwlgcr, WR_LVL_HW_EN, WR_LVL_HW_EN);
+
+	mdelay(1);
+
+	out_be32(&mmdc->mdscr, (CMD_ADDR_LSB_MR_ADDR(0x4) | CONFIGURATION_REQ |
+				CMD_LOAD_MODE_REG | CMD_BANK_ADDR_1));
+	out_be32(&mmdc->mdscr, CONFIGURATION_REQ);
+
+	mdelay(1);
+
+       /* Calibrations now: Read DQS gating calibration */
+	out_be32(&mmdc->mdscr, (CMD_ADDR_MSB_MR_OP(0x4) | CONFIGURATION_REQ |
+				CMD_PRECHARGE_BANK_OPEN | CMD_BANK_ADDR_0));
+	out_be32(&mmdc->mdscr, (CMD_ADDR_LSB_MR_ADDR(0x4) | CONFIGURATION_REQ |
+				CMD_LOAD_MODE_REG | CMD_BANK_ADDR_3));
+	out_be32(&mmdc->mppdcmpr2, MPR_COMPARE_EN);
+	out_be32(&mmdc->mprddlctl, CONFIG_SYS_MMDC_PHY_RD_DLY_LINES_CFG);
+	set_wait_for_bits_clear(&mmdc->mpdgctrl0,
+				AUTO_RD_DQS_GATING_CALIBRATION_EN,
+				AUTO_RD_DQS_GATING_CALIBRATION_EN);
+
+	out_be32(&mmdc->mdscr, (CONFIGURATION_REQ | CMD_LOAD_MODE_REG |
+				CMD_BANK_ADDR_3));
+
+       /* Calibrations now: Read calibration */
+	out_be32(&mmdc->mdscr, (CMD_ADDR_MSB_MR_OP(0x4) | CONFIGURATION_REQ |
+				CMD_PRECHARGE_BANK_OPEN | CMD_BANK_ADDR_0));
+	out_be32(&mmdc->mdscr, (CMD_ADDR_LSB_MR_ADDR(0x4) | CONFIGURATION_REQ |
+				CMD_LOAD_MODE_REG | CMD_BANK_ADDR_3));
+	out_be32(&mmdc->mppdcmpr2,  MPR_COMPARE_EN);
+	set_wait_for_bits_clear(&mmdc->mprddlhwctl,
+				AUTO_RD_CALIBRATION_EN,
+				AUTO_RD_CALIBRATION_EN);
+
+	out_be32(&mmdc->mdscr, (CONFIGURATION_REQ | CMD_LOAD_MODE_REG |
+				CMD_BANK_ADDR_3));
+
+       /* PD, SR */
+	out_be32(&mmdc->mdpdc, CONFIG_SYS_MMDC_CORE_PWR_DOWN_CTRL);
+	out_be32(&mmdc->mapsr, CONFIG_SYS_MMDC_CORE_PWR_SAV_CTRL_STAT);
+
+       /* refresh scheme */
+	set_wait_for_bits_clear(&mmdc->mdref,
+				CONFIG_SYS_MMDC_CORE_REFRESH_CTL,
+				START_REFRESH);
+
+       /* disable CON_REQ */
+	out_be32(&mmdc->mdscr, DISABLE_CFG_REQ);
+}
+
+int dram_init(void)
+{
+	mmdc_init();
+
+	gd->ram_size = CONFIG_SYS_SDRAM_SIZE;
+
+	return 0;
+}
+
+int board_eth_init(bd_t *bis)
+{
+	return pci_eth_init(bis);
+}
+
+int board_early_init_f(void)
+{
+	fsl_lsch2_early_init_f();
+
+	return 0;
+}
+
+int board_init(void)
+{
+	struct ccsr_cci400 *cci = (struct ccsr_cci400 *)CONFIG_SYS_CCI400_ADDR;
+	/*
+	 * Set CCI-400 control override register to enable barrier
+	 * transaction
+	 */
+	out_le32(&cci->ctrl_ord, CCI400_CTRLORD_EN_BARRIER);
+
+#ifdef CONFIG_ENV_IS_NOWHERE
+	gd->env_addr = (ulong)&default_environment[0];
+#endif
+
+#ifdef CONFIG_LAYERSCAPE_NS_ACCESS
+	enable_layerscape_ns_access();
+#endif
+
+	return 0;
+}
+
+int ft_board_setup(void *blob, bd_t *bd)
+{
+	arch_fixup_fdt(blob);
+
+	ft_cpu_setup(blob, bd);
+
+	return 0;
+}
diff --git a/board/freescale/ls1012aqds/Kconfig b/board/freescale/ls1012aqds/Kconfig
new file mode 100644
index 0000000..1257ec8
--- /dev/null
+++ b/board/freescale/ls1012aqds/Kconfig
@@ -0,0 +1,15 @@
+if TARGET_LS1012AQDS
+
+config SYS_BOARD
+	default "ls1012aqds"
+
+config SYS_VENDOR
+	default "freescale"
+
+config SYS_SOC
+	default "fsl-layerscape"
+
+config SYS_CONFIG_NAME
+	default "ls1012aqds"
+
+endif
diff --git a/board/freescale/ls1012aqds/MAINTAINERS b/board/freescale/ls1012aqds/MAINTAINERS
new file mode 100644
index 0000000..27c4aff
--- /dev/null
+++ b/board/freescale/ls1012aqds/MAINTAINERS
@@ -0,0 +1,6 @@
+LS1012AQDS BOARD
+M:	Prabhakar Kushwaha <prabhakar.kushwaha@nxp.com>
+S:	Maintained
+F:	board/freescale/ls1012aqds/
+F:	include/configs/ls1012aqds.h
+F:	configs/ls1012aqds_qspi_defconfig
diff --git a/board/freescale/ls1012aqds/Makefile b/board/freescale/ls1012aqds/Makefile
new file mode 100644
index 0000000..0b813f9
--- /dev/null
+++ b/board/freescale/ls1012aqds/Makefile
@@ -0,0 +1,7 @@
+#
+# Copyright 2016 Freescale Semiconductor, Inc.
+#
+# SPDX-License-Identifier:      GPL-2.0+
+#
+
+obj-y += ls1012aqds.o
diff --git a/board/freescale/ls1012aqds/README b/board/freescale/ls1012aqds/README
new file mode 100644
index 0000000..dee4b30
--- /dev/null
+++ b/board/freescale/ls1012aqds/README
@@ -0,0 +1,59 @@
+Overview
+--------
+QorIQ LS1012A Development System (LS1012AQDS) is a high-performance
+development platform, with a complete debugging environment.
+The LS1012AQDS board supports the QorIQ LS1012A processor and is
+optimized to support the high-bandwidth DDR3L memory and
+a full complement of high-speed SerDes ports.
+
+LS1012A SoC Overview
+--------------------
+Please refer arch/arm/cpu/armv8/fsl-layerscape/doc/README.soc for LS1012A
+SoC overview.
+
+LS1012AQDS board Overview
+-----------------------
+ - SERDES Connections, 4 lanes supporting:
+      - PCI Express - 3.0
+      - SGMII, SGMII 2.5
+      - SATA 3.0
+ - DDR Controller
+     - 16-bit, 1 GB DDR3L SDRAM memory, running at data rates up to 1 GT/s
+ - QSPI Controller
+     - A dual 1:3 switch, NX3L4357GM,115 (U35) drives the QSPI chip-select
+       signals to QSPI NOR flash memory (2 virtual banks) and the QSPI
+       emulator
+ - USB 3.0
+    - One USB 3.0 controller with integrated PHY
+    - One high-speed USB 3.0 port
+ - USB 2.0
+    - One USB 2.0 controller with ULPI interface
+ - Two enhanced secure digital host controllers:
+    - SDHC1 controller can be connected to onboard SDHC connector
+    - SDHC2 controller: 1-/4-bit SD/MMC card supporting 1.8 V devices
+ - 2 I2C controllers
+ - One SATA onboard connectors
+ - UART
+ - 5 SAI
+    - One SAI port with audio codec SGTL5000:
+	• Provides MIC bias
+	• Provides headphone and line output
+    - One SAI port terminated at 2x6 header
+    - Three SAI Tx/Rx ports terminated at 2x3 headers
+ - ARM JTAG support
+
+Booting Options
+---------------
+a) QSPI Flash Emu Boot
+b) QSPI Flash 1
+c) QSPI Flash 2
+
+QSPI flash map
+--------------
+Images		| Size	|QSPI Flash Address
+------------------------------------------
+RCW + PBI	| 1MB	| 0x4000_0000
+U-boot 		| 1MB	| 0x4010_0000
+U-boot Env 	| 1MB	| 0x4020_0000
+PPA FIT image	| 2MB	| 0x4050_0000
+Linux ITB	| ~53MB | 0x40A0_0000
diff --git a/board/freescale/ls1012aqds/ls1012aqds.c b/board/freescale/ls1012aqds/ls1012aqds.c
new file mode 100644
index 0000000..71eea82
--- /dev/null
+++ b/board/freescale/ls1012aqds/ls1012aqds.c
@@ -0,0 +1,234 @@
+/*
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <fdt_support.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/fsl_serdes.h>
+#include <asm/arch/fdt.h>
+#include <asm/arch/soc.h>
+#include <ahci.h>
+#include <hwconfig.h>
+#include <mmc.h>
+#include <scsi.h>
+#include <fm_eth.h>
+#include <fsl_csu.h>
+#include <fsl_esdhc.h>
+#include <fsl_mmdc.h>
+#include <spl.h>
+#include <netdev.h>
+
+#include "../common/qixis.h"
+#include "ls1012aqds_qixis.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static void set_wait_for_bits_clear(void *ptr, u32 value, u32 bits)
+{
+	int timeout = 1000;
+
+	out_be32(ptr, value);
+
+	while (in_be32(ptr) & bits) {
+		udelay(100);
+		timeout--;
+	}
+	if (timeout <= 0)
+		puts("Error: wait for clear timeout.\n");
+}
+
+int checkboard(void)
+{
+	char buf[64];
+	u8 sw;
+
+	sw = QIXIS_READ(arch);
+	printf("Board Arch: V%d, ", sw >> 4);
+	printf("Board version: %c, boot from ", (sw & 0xf) + 'A' - 1);
+
+	sw = QIXIS_READ(brdcfg[QIXIS_LBMAP_BRDCFG_REG]);
+
+	if (sw & QIXIS_LBMAP_ALTBANK)
+		printf("flash: 2\n");
+	else
+		printf("flash: 1\n");
+
+	printf("FPGA: v%d (%s), build %d",
+	       (int)QIXIS_READ(scver), qixis_read_tag(buf),
+	       (int)qixis_read_minor());
+
+	/* the timestamp string contains "\n" at the end */
+	printf(" on %s", qixis_read_time(buf));
+	return 0;
+}
+
+void mmdc_init(void)
+{
+	struct mmdc_p_regs *mmdc =
+		(struct mmdc_p_regs *)CONFIG_SYS_FSL_DDR_ADDR;
+
+	out_be32(&mmdc->mdscr, CONFIGURATION_REQ);
+
+	/* configure timing parms */
+	out_be32(&mmdc->mdotc,  CONFIG_SYS_MMDC_CORE_ODT_TIMING);
+	out_be32(&mmdc->mdcfg0, CONFIG_SYS_MMDC_CORE_TIMING_CFG_0);
+	out_be32(&mmdc->mdcfg1, CONFIG_SYS_MMDC_CORE_TIMING_CFG_1);
+	out_be32(&mmdc->mdcfg2, CONFIG_SYS_MMDC_CORE_TIMING_CFG_2);
+
+	/* other parms	*/
+	out_be32(&mmdc->mdmisc,    CONFIG_SYS_MMDC_CORE_MISC);
+	out_be32(&mmdc->mpmur0,    CONFIG_SYS_MMDC_PHY_MEASURE_UNIT);
+	out_be32(&mmdc->mdrwd,     CONFIG_SYS_MMDC_CORE_RDWR_CMD_DELAY);
+	out_be32(&mmdc->mpodtctrl, CONFIG_SYS_MMDC_PHY_ODT_CTRL);
+
+	/* out of reset delays */
+	out_be32(&mmdc->mdor,  CONFIG_SYS_MMDC_CORE_OUT_OF_RESET_DELAY);
+
+	/* physical parms */
+	out_be32(&mmdc->mdctl, CONFIG_SYS_MMDC_CORE_CONTROL_1);
+	out_be32(&mmdc->mdasp, CONFIG_SYS_MMDC_CORE_ADDR_PARTITION);
+
+       /* Enable MMDC */
+	out_be32(&mmdc->mdctl, CONFIG_SYS_MMDC_CORE_CONTROL_2);
+
+	/* dram init sequence: update MRs */
+	out_be32(&mmdc->mdscr, (CMD_ADDR_LSB_MR_ADDR(0x8) | CONFIGURATION_REQ |
+				CMD_LOAD_MODE_REG | CMD_BANK_ADDR_2));
+	out_be32(&mmdc->mdscr, (CONFIGURATION_REQ | CMD_LOAD_MODE_REG |
+				CMD_BANK_ADDR_3));
+	out_be32(&mmdc->mdscr, (CMD_ADDR_LSB_MR_ADDR(0x4) | CONFIGURATION_REQ |
+				CMD_LOAD_MODE_REG | CMD_BANK_ADDR_1));
+	out_be32(&mmdc->mdscr, (CMD_ADDR_MSB_MR_OP(0x19) |
+				CMD_ADDR_LSB_MR_ADDR(0x30) | CONFIGURATION_REQ |
+				CMD_LOAD_MODE_REG | CMD_BANK_ADDR_0));
+
+       /* dram init sequence: ZQCL */
+	out_be32(&mmdc->mdscr, (CMD_ADDR_MSB_MR_OP(0x4) | CONFIGURATION_REQ |
+				CMD_ZQ_CALIBRATION | CMD_BANK_ADDR_0));
+	set_wait_for_bits_clear(&mmdc->mpzqhwctrl,
+				CONFIG_SYS_MMDC_PHY_ZQ_HW_CTRL,
+				FORCE_ZQ_AUTO_CALIBRATION);
+
+       /* Calibrations now: wr lvl */
+	out_be32(&mmdc->mdscr, (CMD_ADDR_LSB_MR_ADDR(0x84) |
+				CONFIGURATION_REQ | CMD_LOAD_MODE_REG |
+				CMD_BANK_ADDR_1));
+	out_be32(&mmdc->mdscr, (CONFIGURATION_REQ | WL_EN | CMD_NORMAL));
+	set_wait_for_bits_clear(&mmdc->mpwlgcr, WR_LVL_HW_EN, WR_LVL_HW_EN);
+
+	mdelay(1);
+
+	out_be32(&mmdc->mdscr, (CMD_ADDR_LSB_MR_ADDR(0x4) | CONFIGURATION_REQ |
+				CMD_LOAD_MODE_REG | CMD_BANK_ADDR_1));
+	out_be32(&mmdc->mdscr, CONFIGURATION_REQ);
+
+	mdelay(1);
+
+       /* Calibrations now: Read DQS gating calibration */
+	out_be32(&mmdc->mdscr, (CMD_ADDR_MSB_MR_OP(0x4) | CONFIGURATION_REQ |
+				CMD_PRECHARGE_BANK_OPEN | CMD_BANK_ADDR_0));
+	out_be32(&mmdc->mdscr, (CMD_ADDR_LSB_MR_ADDR(0x4) | CONFIGURATION_REQ |
+				CMD_LOAD_MODE_REG | CMD_BANK_ADDR_3));
+	out_be32(&mmdc->mppdcmpr2, MPR_COMPARE_EN);
+	out_be32(&mmdc->mprddlctl, CONFIG_SYS_MMDC_PHY_RD_DLY_LINES_CFG);
+	set_wait_for_bits_clear(&mmdc->mpdgctrl0,
+				AUTO_RD_DQS_GATING_CALIBRATION_EN,
+				AUTO_RD_DQS_GATING_CALIBRATION_EN);
+
+	out_be32(&mmdc->mdscr, (CONFIGURATION_REQ | CMD_LOAD_MODE_REG |
+				CMD_BANK_ADDR_3));
+
+       /* Calibrations now: Read calibration */
+	out_be32(&mmdc->mdscr, (CMD_ADDR_MSB_MR_OP(0x4) | CONFIGURATION_REQ |
+				CMD_PRECHARGE_BANK_OPEN | CMD_BANK_ADDR_0));
+	out_be32(&mmdc->mdscr, (CMD_ADDR_LSB_MR_ADDR(0x4) | CONFIGURATION_REQ |
+				CMD_LOAD_MODE_REG | CMD_BANK_ADDR_3));
+	out_be32(&mmdc->mppdcmpr2,  MPR_COMPARE_EN);
+	set_wait_for_bits_clear(&mmdc->mprddlhwctl,
+				AUTO_RD_CALIBRATION_EN,
+				AUTO_RD_CALIBRATION_EN);
+
+	out_be32(&mmdc->mdscr, (CONFIGURATION_REQ | CMD_LOAD_MODE_REG |
+				CMD_BANK_ADDR_3));
+
+       /* PD, SR */
+	out_be32(&mmdc->mdpdc, CONFIG_SYS_MMDC_CORE_PWR_DOWN_CTRL);
+	out_be32(&mmdc->mapsr, CONFIG_SYS_MMDC_CORE_PWR_SAV_CTRL_STAT);
+
+       /* refresh scheme */
+	set_wait_for_bits_clear(&mmdc->mdref,
+				CONFIG_SYS_MMDC_CORE_REFRESH_CTL,
+				START_REFRESH);
+
+       /* disable CON_REQ */
+	out_be32(&mmdc->mdscr, DISABLE_CFG_REQ);
+}
+
+int dram_init(void)
+{
+	mmdc_init();
+
+	gd->ram_size = CONFIG_SYS_SDRAM_SIZE;
+
+	return 0;
+}
+
+int board_early_init_f(void)
+{
+	fsl_lsch2_early_init_f();
+
+	return 0;
+}
+
+#ifdef CONFIG_MISC_INIT_R
+int misc_init_r(void)
+{
+	u8 mux_sdhc_cd = 0x80;
+
+	i2c_set_bus_num(0);
+
+	i2c_write(CONFIG_SYS_I2C_FPGA_ADDR, 0x5a, 1, &mux_sdhc_cd, 1);
+	return 0;
+}
+#endif
+
+int board_init(void)
+{
+	struct ccsr_cci400 *cci = (struct ccsr_cci400 *)
+				   CONFIG_SYS_CCI400_ADDR;
+
+	/* Set CCI-400 control override register to enable barrier
+	 * transaction */
+	out_le32(&cci->ctrl_ord,
+		 CCI400_CTRLORD_EN_BARRIER);
+
+#ifdef CONFIG_LAYERSCAPE_NS_ACCESS
+	enable_layerscape_ns_access();
+#endif
+
+#ifdef CONFIG_ENV_IS_NOWHERE
+	gd->env_addr = (ulong)&default_environment[0];
+#endif
+	return 0;
+}
+
+int board_eth_init(bd_t *bis)
+{
+	return pci_eth_init(bis);
+}
+
+#ifdef CONFIG_OF_BOARD_SETUP
+int ft_board_setup(void *blob, bd_t *bd)
+{
+	arch_fixup_fdt(blob);
+
+	ft_cpu_setup(blob, bd);
+
+	return 0;
+}
+#endif
diff --git a/board/freescale/ls1012aqds/ls1012aqds_qixis.h b/board/freescale/ls1012aqds/ls1012aqds_qixis.h
new file mode 100644
index 0000000..584f604
--- /dev/null
+++ b/board/freescale/ls1012aqds/ls1012aqds_qixis.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __LS1043AQDS_QIXIS_H__
+#define __LS1043AQDS_QIXIS_H__
+
+/* Definitions of QIXIS Registers for LS1043AQDS */
+
+/* BRDCFG4[4:7] select EC1 and EC2 as a pair */
+#define BRDCFG4_EMISEL_MASK		0xe0
+#define BRDCFG4_EMISEL_SHIFT		5
+
+/* SYSCLK */
+#define QIXIS_SYSCLK_66			0x0
+#define QIXIS_SYSCLK_83			0x1
+#define QIXIS_SYSCLK_100		0x2
+#define QIXIS_SYSCLK_125		0x3
+#define QIXIS_SYSCLK_133		0x4
+
+/* DDRCLK */
+#define QIXIS_DDRCLK_66			0x0
+#define QIXIS_DDRCLK_100		0x1
+#define QIXIS_DDRCLK_125		0x2
+#define QIXIS_DDRCLK_133		0x3
+
+/* BRDCFG2 - SD clock*/
+#define QIXIS_SDCLK1_100		0x0
+#define QIXIS_SDCLK1_125		0x1
+#define QIXIS_SDCLK1_165		0x2
+#define QIXIS_SDCLK1_100_SP		0x3
+
+#endif
diff --git a/board/freescale/ls1012ardb/Kconfig b/board/freescale/ls1012ardb/Kconfig
new file mode 100644
index 0000000..3f67c28
--- /dev/null
+++ b/board/freescale/ls1012ardb/Kconfig
@@ -0,0 +1,15 @@
+if TARGET_LS1012ARDB
+
+config SYS_BOARD
+	default "ls1012ardb"
+
+config SYS_VENDOR
+	default "freescale"
+
+config SYS_SOC
+	default "fsl-layerscape"
+
+config SYS_CONFIG_NAME
+	default "ls1012ardb"
+
+endif
diff --git a/board/freescale/ls1012ardb/MAINTAINERS b/board/freescale/ls1012ardb/MAINTAINERS
new file mode 100644
index 0000000..79a2a7d
--- /dev/null
+++ b/board/freescale/ls1012ardb/MAINTAINERS
@@ -0,0 +1,6 @@
+LS1012ARDB BOARD
+M:	Prabhakar Kushwaha <prabhakar.kushwaha@nxp.com>
+S:	Maintained
+F:	board/freescale/ls1012ardb/
+F:	include/configs/ls1012ardb.h
+F:	configs/ls1012ardb_qspi_defconfig
diff --git a/board/freescale/ls1012ardb/Makefile b/board/freescale/ls1012ardb/Makefile
new file mode 100644
index 0000000..05fa9d9
--- /dev/null
+++ b/board/freescale/ls1012ardb/Makefile
@@ -0,0 +1,7 @@
+#
+# Copyright 2016 Freescale Semiconductor, Inc.
+#
+# SPDX-License-Identifier:      GPL-2.0+
+#
+
+obj-y += ls1012ardb.o
diff --git a/board/freescale/ls1012ardb/README b/board/freescale/ls1012ardb/README
new file mode 100644
index 0000000..453b432
--- /dev/null
+++ b/board/freescale/ls1012ardb/README
@@ -0,0 +1,54 @@
+Overview
+--------
+QorIQ LS1012A Reference Design System (LS1012ARDB) is a high-performance
+development platform, with a complete debugging environment.
+The LS1012ARDB board supports the QorIQ LS1012A processor and is
+optimized to support the high-bandwidth DDR3L memory and
+a full complement of high-speed SerDes ports.
+
+LS1012A SoC Overview
+--------------------
+Please refer arch/arm/cpu/armv8/fsl-layerscape/doc/README.soc for LS2080A
+SoC overview.
+
+LS1012ARDB board Overview
+-----------------------
+ - SERDES Connections, 4 lanes supporting:
+      - PCI Express - 3.0
+      - SGMII, SGMII 2.5
+      - SATA 3.0
+ - DDR Controller
+     - 16-bit, 1 GB DDR3L SDRAM memory, running at data rates up to 1 GT/s
+ -QSPI: A dual 1:3 switch, NX3L4357GM,115 (U35) drives the QSPI chip-select
+ signals to
+    - QSPI NOR flash memory (2 virtual banks)
+    - the QSPI emulator.s
+ - USB 3.0
+    - one high-speed USB 2.0/3.0 port.
+ - Two enhanced secure digital host controllers:
+    - SDHC1 controller can be connected to onboard SDHC connector
+    - SDHC2 controller: Three dual 1:4 mux/demux devices,
+    74CBTLV3253DS (U30, U31, U33) drive the SDHC2 signals to eMMC,
+    SDIO WiFi, SPI, and Ardiuno shield
+ - 2 I2C controllers
+ - One SATA onboard connectors
+ - UART
+   - The LS1012A processor consists of two UART controllers,
+   out of which only UART1 is used on RDB.
+ - ARM JTAG support
+
+Booting Options
+---------------
+a) QSPI Flash Emu Boot
+b) QSPI Flash 1
+c) QSPI Flash 2
+
+QSPI flash map
+--------------
+Images		| Size	|QSPI Flash Address
+------------------------------------------
+RCW + PBI	| 1MB	| 0x4000_0000
+U-boot 		| 1MB	| 0x4010_0000
+U-boot Env 	| 1MB	| 0x4020_0000
+PPA FIT image	| 2MB	| 0x4050_0000
+Linux ITB	| ~53MB | 0x40A0_0000
diff --git a/board/freescale/ls1012ardb/ls1012ardb.c b/board/freescale/ls1012ardb/ls1012ardb.c
new file mode 100644
index 0000000..f69768d
--- /dev/null
+++ b/board/freescale/ls1012ardb/ls1012ardb.c
@@ -0,0 +1,224 @@
+/*
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/fsl_serdes.h>
+#include <asm/arch/soc.h>
+#include <hwconfig.h>
+#include <ahci.h>
+#include <mmc.h>
+#include <scsi.h>
+#include <fsl_csu.h>
+#include <fsl_esdhc.h>
+#include <environment.h>
+#include <fsl_mmdc.h>
+#include <netdev.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static void set_wait_for_bits_clear(void *ptr, u32 value, u32 bits)
+{
+	int timeout = 1000;
+
+	out_be32(ptr, value);
+
+	while (in_be32(ptr) & bits) {
+		udelay(100);
+		timeout--;
+	}
+	if (timeout <= 0)
+		puts("Error: wait for clear timeout.\n");
+}
+
+int checkboard(void)
+{
+	u8 in1;
+
+	puts("Board: LS1012ARDB ");
+
+	/* Initialize i2c early for Serial flash bank information */
+	i2c_set_bus_num(0);
+
+	if (i2c_read(I2C_MUX_IO1_ADDR, 1, 1, &in1, 1) < 0) {
+		printf("Error reading i2c boot information!\n");
+		return 0; /* Don't want to hang() on this error */
+	}
+
+	puts("Version");
+	if ((in1 & (~__SW_REV_MASK)) == __SW_REV_A)
+		puts(": RevA");
+	else if ((in1 & (~__SW_REV_MASK)) == __SW_REV_B)
+		puts(": RevB");
+	else
+		puts(": unknown");
+
+	printf(", boot from QSPI");
+	if ((in1 & (~__SW_BOOT_MASK)) == __SW_BOOT_EMU)
+		puts(": emu\n");
+	else if ((in1 & (~__SW_BOOT_MASK)) == __SW_BOOT_BANK1)
+		puts(": bank1\n");
+	else if ((in1 & (~__SW_BOOT_MASK)) == __SW_BOOT_BANK2)
+		puts(": bank2\n");
+	else
+		puts("unknown\n");
+
+	return 0;
+}
+
+void mmdc_init(void)
+{
+	struct mmdc_p_regs *mmdc =
+		(struct mmdc_p_regs *)CONFIG_SYS_FSL_DDR_ADDR;
+
+	out_be32(&mmdc->mdscr, CONFIGURATION_REQ);
+
+	/* configure timing parms */
+	out_be32(&mmdc->mdotc,  CONFIG_SYS_MMDC_CORE_ODT_TIMING);
+	out_be32(&mmdc->mdcfg0, CONFIG_SYS_MMDC_CORE_TIMING_CFG_0);
+	out_be32(&mmdc->mdcfg1, CONFIG_SYS_MMDC_CORE_TIMING_CFG_1);
+	out_be32(&mmdc->mdcfg2, CONFIG_SYS_MMDC_CORE_TIMING_CFG_2);
+
+	/* other parms	*/
+	out_be32(&mmdc->mdmisc,    CONFIG_SYS_MMDC_CORE_MISC);
+	out_be32(&mmdc->mpmur0,    CONFIG_SYS_MMDC_PHY_MEASURE_UNIT);
+	out_be32(&mmdc->mdrwd,     CONFIG_SYS_MMDC_CORE_RDWR_CMD_DELAY);
+	out_be32(&mmdc->mpodtctrl, CONFIG_SYS_MMDC_PHY_ODT_CTRL);
+
+	/* out of reset delays */
+	out_be32(&mmdc->mdor,  CONFIG_SYS_MMDC_CORE_OUT_OF_RESET_DELAY);
+
+	/* physical parms */
+	out_be32(&mmdc->mdctl, CONFIG_SYS_MMDC_CORE_CONTROL_1);
+	out_be32(&mmdc->mdasp, CONFIG_SYS_MMDC_CORE_ADDR_PARTITION);
+
+       /* Enable MMDC */
+	out_be32(&mmdc->mdctl, CONFIG_SYS_MMDC_CORE_CONTROL_2);
+
+	/* dram init sequence: update MRs */
+	out_be32(&mmdc->mdscr, (CMD_ADDR_LSB_MR_ADDR(0x8) | CONFIGURATION_REQ |
+				CMD_LOAD_MODE_REG | CMD_BANK_ADDR_2));
+	out_be32(&mmdc->mdscr, (CONFIGURATION_REQ | CMD_LOAD_MODE_REG |
+				CMD_BANK_ADDR_3));
+	out_be32(&mmdc->mdscr, (CMD_ADDR_LSB_MR_ADDR(0x4) | CONFIGURATION_REQ |
+				CMD_LOAD_MODE_REG | CMD_BANK_ADDR_1));
+	out_be32(&mmdc->mdscr, (CMD_ADDR_MSB_MR_OP(0x19) |
+				CMD_ADDR_LSB_MR_ADDR(0x30) | CONFIGURATION_REQ |
+				CMD_LOAD_MODE_REG | CMD_BANK_ADDR_0));
+
+       /* dram init sequence: ZQCL */
+	out_be32(&mmdc->mdscr, (CMD_ADDR_MSB_MR_OP(0x4) | CONFIGURATION_REQ |
+				CMD_ZQ_CALIBRATION | CMD_BANK_ADDR_0));
+	set_wait_for_bits_clear(&mmdc->mpzqhwctrl,
+				CONFIG_SYS_MMDC_PHY_ZQ_HW_CTRL,
+				FORCE_ZQ_AUTO_CALIBRATION);
+
+       /* Calibrations now: wr lvl */
+	out_be32(&mmdc->mdscr, (CMD_ADDR_LSB_MR_ADDR(0x84) |
+				CONFIGURATION_REQ | CMD_LOAD_MODE_REG |
+				CMD_BANK_ADDR_1));
+	out_be32(&mmdc->mdscr, (CONFIGURATION_REQ | WL_EN | CMD_NORMAL));
+	set_wait_for_bits_clear(&mmdc->mpwlgcr, WR_LVL_HW_EN, WR_LVL_HW_EN);
+
+	mdelay(1);
+
+	out_be32(&mmdc->mdscr, (CMD_ADDR_LSB_MR_ADDR(0x4) | CONFIGURATION_REQ |
+				CMD_LOAD_MODE_REG | CMD_BANK_ADDR_1));
+	out_be32(&mmdc->mdscr, CONFIGURATION_REQ);
+
+	mdelay(1);
+
+       /* Calibrations now: Read DQS gating calibration */
+	out_be32(&mmdc->mdscr, (CMD_ADDR_MSB_MR_OP(0x4) | CONFIGURATION_REQ |
+				CMD_PRECHARGE_BANK_OPEN | CMD_BANK_ADDR_0));
+	out_be32(&mmdc->mdscr, (CMD_ADDR_LSB_MR_ADDR(0x4) | CONFIGURATION_REQ |
+				CMD_LOAD_MODE_REG | CMD_BANK_ADDR_3));
+	out_be32(&mmdc->mppdcmpr2, MPR_COMPARE_EN);
+	out_be32(&mmdc->mprddlctl, CONFIG_SYS_MMDC_PHY_RD_DLY_LINES_CFG);
+	set_wait_for_bits_clear(&mmdc->mpdgctrl0,
+				AUTO_RD_DQS_GATING_CALIBRATION_EN,
+				AUTO_RD_DQS_GATING_CALIBRATION_EN);
+
+	out_be32(&mmdc->mdscr, (CONFIGURATION_REQ | CMD_LOAD_MODE_REG |
+				CMD_BANK_ADDR_3));
+
+       /* Calibrations now: Read calibration */
+	out_be32(&mmdc->mdscr, (CMD_ADDR_MSB_MR_OP(0x4) | CONFIGURATION_REQ |
+				CMD_PRECHARGE_BANK_OPEN | CMD_BANK_ADDR_0));
+	out_be32(&mmdc->mdscr, (CMD_ADDR_LSB_MR_ADDR(0x4) | CONFIGURATION_REQ |
+				CMD_LOAD_MODE_REG | CMD_BANK_ADDR_3));
+	out_be32(&mmdc->mppdcmpr2,  MPR_COMPARE_EN);
+	set_wait_for_bits_clear(&mmdc->mprddlhwctl,
+				AUTO_RD_CALIBRATION_EN,
+				AUTO_RD_CALIBRATION_EN);
+
+	out_be32(&mmdc->mdscr, (CONFIGURATION_REQ | CMD_LOAD_MODE_REG |
+				CMD_BANK_ADDR_3));
+
+       /* PD, SR */
+	out_be32(&mmdc->mdpdc, CONFIG_SYS_MMDC_CORE_PWR_DOWN_CTRL);
+	out_be32(&mmdc->mapsr, CONFIG_SYS_MMDC_CORE_PWR_SAV_CTRL_STAT);
+
+       /* refresh scheme */
+	set_wait_for_bits_clear(&mmdc->mdref,
+				CONFIG_SYS_MMDC_CORE_REFRESH_CTL,
+				START_REFRESH);
+
+       /* disable CON_REQ */
+	out_be32(&mmdc->mdscr, DISABLE_CFG_REQ);
+}
+
+int dram_init(void)
+{
+	mmdc_init();
+
+	gd->ram_size = CONFIG_SYS_SDRAM_SIZE;
+
+	return 0;
+}
+
+int board_eth_init(bd_t *bis)
+{
+	return pci_eth_init(bis);
+}
+
+int board_early_init_f(void)
+{
+	fsl_lsch2_early_init_f();
+
+	return 0;
+}
+
+int board_init(void)
+{
+	struct ccsr_cci400 *cci = (struct ccsr_cci400 *)CONFIG_SYS_CCI400_ADDR;
+	/*
+	 * Set CCI-400 control override register to enable barrier
+	 * transaction
+	 */
+	out_le32(&cci->ctrl_ord, CCI400_CTRLORD_EN_BARRIER);
+
+#ifdef CONFIG_ENV_IS_NOWHERE
+	gd->env_addr = (ulong)&default_environment[0];
+#endif
+
+#ifdef CONFIG_LAYERSCAPE_NS_ACCESS
+	enable_layerscape_ns_access();
+#endif
+
+	return 0;
+}
+
+int ft_board_setup(void *blob, bd_t *bd)
+{
+	arch_fixup_fdt(blob);
+
+	ft_cpu_setup(blob, bd);
+
+	return 0;
+}
diff --git a/board/freescale/ls1021aqds/ddr.h b/board/freescale/ls1021aqds/ddr.h
index f819c99..b39b561 100644
--- a/board/freescale/ls1021aqds/ddr.h
+++ b/board/freescale/ls1021aqds/ddr.h
@@ -31,21 +31,21 @@
 	 * ranks| mhz| GB  |adjst| start |   ctl2    |  ctl3  |      |delay |
 	 */
 #ifdef CONFIG_SYS_FSL_DDR4
-	{2,  1666, 0, 4,     7, 0x0808090B, 0x0C0D0E0A,},
-	{2,  1900, 0, 4,     6, 0x08080A0C, 0x0D0E0F0A,},
-	{1,  1666, 0, 4,     8, 0x090A0B0B, 0x0C0D0E0C,},
-	{1,  1900, 0, 4,     9, 0x0A0B0C0B, 0x0D0E0F0D,},
-	{1,  2200, 0, 4,    10, 0x0B0C0D0C, 0x0E0F110E,},
+	{2,  1666, 0, 8,     7, 0x0808090B, 0x0C0D0E0A,},
+	{2,  1900, 0, 8,     6, 0x08080A0C, 0x0D0E0F0A,},
+	{1,  1666, 0, 8,     8, 0x090A0B0B, 0x0C0D0E0C,},
+	{1,  1900, 0, 8,     9, 0x0A0B0C0B, 0x0D0E0F0D,},
+	{1,  2200, 0, 8,    10, 0x0B0C0D0C, 0x0E0F110E,},
 #elif defined(CONFIG_SYS_FSL_DDR3)
-	{1,  833,  1, 6,     8, 0x06060607, 0x08080807,   0x1f,    2,  0},
-	{1,  1350, 1, 6,     8, 0x0708080A, 0x0A0B0C09,   0x1f,    2,  0},
-	{1,  833,  2, 6,     8, 0x06060607, 0x08080807,   0x1f,    2,  0},
-	{1,  1350, 2, 6,     8, 0x0708080A, 0x0A0B0C09,   0x1f,    2,  0},
-	{2,  833,  4, 6,     8, 0x06060607, 0x08080807,   0x1f,    2,  0},
-	{2,  1350, 4, 6,     8, 0x0708080A, 0x0A0B0C09,   0x1f,    2,  0},
-	{2,  1350, 0, 6,     8, 0x0708080A, 0x0A0B0C09,   0x1f,    2,  0},
-	{2,  1666, 4, 4,   0xa, 0x0B08090C, 0x0B0E0D0A,   0x1f,    2,  0},
-	{2,  1666, 0, 4,   0xa, 0x0B08090C, 0x0B0E0D0A,   0x1f,    2,  0},
+	{1,  833,  1, 12,     8, 0x06060607, 0x08080807,   0x1f,    2,  0},
+	{1,  1350, 1, 12,     8, 0x0708080A, 0x0A0B0C09,   0x1f,    2,  0},
+	{1,  833,  2, 12,     8, 0x06060607, 0x08080807,   0x1f,    2,  0},
+	{1,  1350, 2, 12,     8, 0x0708080A, 0x0A0B0C09,   0x1f,    2,  0},
+	{2,  833,  4, 12,     8, 0x06060607, 0x08080807,   0x1f,    2,  0},
+	{2,  1350, 4, 12,     8, 0x0708080A, 0x0A0B0C09,   0x1f,    2,  0},
+	{2,  1350, 0, 12,     8, 0x0708080A, 0x0A0B0C09,   0x1f,    2,  0},
+	{2,  1666, 4, 8,    0xa, 0x0B08090C, 0x0B0E0D0A,   0x1f,    2,  0},
+	{2,  1666, 0, 8,    0xa, 0x0B08090C, 0x0B0E0D0A,   0x1f,    2,  0},
 #else
 #error DDR type not defined
 #endif
diff --git a/board/freescale/ls1043aqds/README b/board/freescale/ls1043aqds/README
index a6fd7a3..913537d 100644
--- a/board/freescale/ls1043aqds/README
+++ b/board/freescale/ls1043aqds/README
@@ -8,41 +8,8 @@
 
 LS1043A SoC Overview
 --------------------
-The LS1043A integrated multicore processor combines four ARM Cortex-A53
-processor cores with datapath acceleration optimized for L2/3 packet
-processing, single pass security offload and robust traffic management
-and quality of service.
-
-The LS1043A SoC includes the following function and features:
- - Four 64-bit ARM Cortex-A53 CPUs
- - 1 MB unified L2 Cache
- - One 32-bit DDR3L/DDR4 SDRAM memory controllers with ECC and interleaving
-   support
- - Data Path Acceleration Architecture (DPAA) incorporating acceleration the
-   the following functions:
-   - Packet parsing, classification, and distribution (FMan)
-   - Queue management for scheduling, packet sequencing, and congestion
-     management (QMan)
-   - Hardware buffer management for buffer allocation and de-allocation (BMan)
-   - Cryptography acceleration (SEC)
- - Ethernet interfaces by FMan
-   - Up to 1 x XFI supporting 10G interface
-   - Up to 1 x QSGMII
-   - Up to 4 x SGMII supporting 1000Mbps
-   - Up to 2 x SGMII supporting 2500Mbps
-   - Up to 2 x RGMII supporting 1000Mbps
- - High-speed peripheral interfaces
-   - Three PCIe 2.0 controllers, one supporting x4 operation
-   - One serial ATA (SATA 3.0) controllers
- - Additional peripheral interfaces
-   - Three high-speed USB 3.0 controllers with integrated PHY
-   - Enhanced secure digital host controller (eSDXC/eMMC)
-   - Quad Serial Peripheral Interface (QSPI) Controller
-   - Serial peripheral interface (SPI) controller
-   - Four I2C controllers
-   - Two DUARTs
-   - Integrated flash controller supporting NAND and NOR flash
- - QorIQ platform's trust architecture 2.1
+Please refer arch/arm/cpu/armv8/fsl-layerscape/doc/README.soc for LS1043A
+SoC overview.
 
  LS1043AQDS board Overview
  -----------------------
diff --git a/board/freescale/ls1043aqds/ddr.h b/board/freescale/ls1043aqds/ddr.h
index d3f4082..ad709ba 100644
--- a/board/freescale/ls1043aqds/ddr.h
+++ b/board/freescale/ls1043aqds/ddr.h
@@ -34,21 +34,21 @@
 	 * ranks| mhz| GB  |adjst| start |   ctl2    |  ctl3  |      |delay |
 	 */
 #ifdef CONFIG_SYS_FSL_DDR4
-	{2,  1666, 0, 4,     7, 0x0808090B, 0x0C0D0E0A,},
-	{2,  1900, 0, 4,     6, 0x08080A0C, 0x0D0E0F0A,},
-	{1,  1666, 0, 4,     6, 0x0708090B, 0x0C0D0E0A,},
-	{1,  1900, 0, 4,     9, 0x0A0B0C0B, 0x0D0E0F0D,},
-	{1,  2200, 0, 4,    10, 0x0B0C0D0C, 0x0E0F110E,},
+	{2,  1666, 0,  8,     7, 0x0808090B, 0x0C0D0E0A,},
+	{2,  1900, 0,  8,     6, 0x08080A0C, 0x0D0E0F0A,},
+	{1,  1666, 0,  8,     6, 0x0708090B, 0x0C0D0E0A,},
+	{1,  1900, 0,  8,     9, 0x0A0B0C0B, 0x0D0E0F0D,},
+	{1,  2200, 0,  8,    10, 0x0B0C0D0C, 0x0E0F110E,},
 #elif defined(CONFIG_SYS_FSL_DDR3)
-	{1,  833,  1, 6,     8, 0x06060607, 0x08080807,   0x1f,    2,  0},
-	{1,  1350, 1, 6,     8, 0x0708080A, 0x0A0B0C09,   0x1f,    2,  0},
-	{1,  833,  2, 6,     8, 0x06060607, 0x08080807,   0x1f,    2,  0},
-	{1,  1350, 2, 6,     8, 0x0708080A, 0x0A0B0C09,   0x1f,    2,  0},
-	{2,  833,  4, 6,     8, 0x06060607, 0x08080807,   0x1f,    2,  0},
-	{2,  1350, 4, 6,     8, 0x0708080A, 0x0A0B0C09,   0x1f,    2,  0},
-	{2,  1350, 0, 6,     8, 0x0708080A, 0x0A0B0C09,   0x1f,    2,  0},
-	{2,  1666, 4, 4,   0xa, 0x0B08090C, 0x0B0E0D0A,   0x1f,    2,  0},
-	{2,  1666, 0, 4,   0xa, 0x0B08090C, 0x0B0E0D0A,   0x1f,    2,  0},
+	{1,  833,  1, 12,     8, 0x06060607, 0x08080807,   0x1f,    2,  0},
+	{1,  1350, 1, 12,     8, 0x0708080A, 0x0A0B0C09,   0x1f,    2,  0},
+	{1,  833,  2, 12,     8, 0x06060607, 0x08080807,   0x1f,    2,  0},
+	{1,  1350, 2, 12,     8, 0x0708080A, 0x0A0B0C09,   0x1f,    2,  0},
+	{2,  833,  4, 12,     8, 0x06060607, 0x08080807,   0x1f,    2,  0},
+	{2,  1350, 4, 12,     8, 0x0708080A, 0x0A0B0C09,   0x1f,    2,  0},
+	{2,  1350, 0, 12,     8, 0x0708080A, 0x0A0B0C09,   0x1f,    2,  0},
+	{2,  1666, 4,  8,   0xa, 0x0B08090C, 0x0B0E0D0A,   0x1f,    2,  0},
+	{2,  1666, 0,  8,   0xa, 0x0B08090C, 0x0B0E0D0A,   0x1f,    2,  0},
 #else
 #error DDR type not defined
 #endif
diff --git a/board/freescale/ls1043aqds/ls1043aqds.c b/board/freescale/ls1043aqds/ls1043aqds.c
index ca393e8..7e47ef0 100644
--- a/board/freescale/ls1043aqds/ls1043aqds.c
+++ b/board/freescale/ls1043aqds/ls1043aqds.c
@@ -238,8 +238,8 @@
 	out_be32(&scfg->rcwpmuxcr0, 0x3333);
 	out_be32(&scfg->usbdrvvbus_selcr, SCFG_USBDRVVBUS_SELCR_USB1);
 	usb_pwrfault =
-		(SCFG_USBPWRFAULT_SHARED << SCFG_USBPWRFAULT_USB3_SHIFT) |
-		(SCFG_USBPWRFAULT_SHARED << SCFG_USBPWRFAULT_USB2_SHIFT) |
+		(SCFG_USBPWRFAULT_DEDICATED << SCFG_USBPWRFAULT_USB3_SHIFT) |
+		(SCFG_USBPWRFAULT_DEDICATED << SCFG_USBPWRFAULT_USB2_SHIFT) |
 		(SCFG_USBPWRFAULT_SHARED << SCFG_USBPWRFAULT_USB1_SHIFT);
 	out_be32(&scfg->usbpwrfault_selcr, usb_pwrfault);
 #endif
diff --git a/board/freescale/ls1043ardb/README b/board/freescale/ls1043ardb/README
index 0556e73..709ddbb 100644
--- a/board/freescale/ls1043ardb/README
+++ b/board/freescale/ls1043ardb/README
@@ -8,41 +8,8 @@
 
 LS1043A SoC Overview
 --------------------
-The LS1043A integrated multicore processor combines four ARM Cortex-A53
-processor cores with datapath acceleration optimized for L2/3 packet
-processing, single pass security offload and robust traffic management
-and quality of service.
-
-The LS1043A SoC includes the following function and features:
- - Four 64-bit ARM Cortex-A53 CPUs
- - 1 MB unified L2 Cache
- - One 32-bit DDR3L/DDR4 SDRAM memory controllers with ECC and interleaving
-   support
- - Data Path Acceleration Architecture (DPAA) incorporating acceleration the
-   the following functions:
-   - Packet parsing, classification, and distribution (FMan)
-   - Queue management for scheduling, packet sequencing, and congestion
-     management (QMan)
-   - Hardware buffer management for buffer allocation and de-allocation (BMan)
-   - Cryptography acceleration (SEC)
- - Ethernet interfaces by FMan
-   - Up to 1 x XFI supporting 10G interface
-   - Up to 1 x QSGMII
-   - Up to 4 x SGMII supporting 1000Mbps
-   - Up to 2 x SGMII supporting 2500Mbps
-   - Up to 2 x RGMII supporting 1000Mbps
- - High-speed peripheral interfaces
-   - Three PCIe 2.0 controllers, one supporting x4 operation
-   - One serial ATA (SATA 3.0) controllers
- - Additional peripheral interfaces
-   - Three high-speed USB 3.0 controllers with integrated PHY
-   - Enhanced secure digital host controller (eSDXC/eMMC)
-   - Quad Serial Peripheral Interface (QSPI) Controller
-   - Serial peripheral interface (SPI) controller
-   - Four I2C controllers
-   - Two DUARTs
-   - Integrated flash controller supporting NAND and NOR flash
- - QorIQ platform's trust architecture 2.1
+Please refer arch/arm/cpu/armv8/fsl-layerscape/doc/README.soc for LS1043A
+SoC overview.
 
  LS1043ARDB board Overview
  -----------------------
diff --git a/board/freescale/ls1043ardb/ddr.h b/board/freescale/ls1043ardb/ddr.h
index 8ca166b..a77ddf3 100644
--- a/board/freescale/ls1043ardb/ddr.h
+++ b/board/freescale/ls1043ardb/ddr.h
@@ -34,9 +34,9 @@
 	 * ranks| mhz| GB  |adjst| start |   ctl2    |  ctl3  |      |delay |
 	 */
 #ifdef CONFIG_SYS_FSL_DDR4
-	{1,  1666, 0, 6,     7, 0x07090800, 0x00000000,},
-	{1,  1900, 0, 6,     7, 0x07090800, 0x00000000,},
-	{1,  2200, 0, 6,     7, 0x07090800, 0x00000000,},
+	{1,  1666, 0, 12,     7, 0x07090800, 0x00000000,},
+	{1,  1900, 0, 12,     7, 0x07090800, 0x00000000,},
+	{1,  2200, 0, 12,     7, 0x07090800, 0x00000000,},
 #endif
 	{}
 };
diff --git a/board/freescale/ls2080aqds/README b/board/freescale/ls2080aqds/README
index 6ddad92..5c98866 100644
--- a/board/freescale/ls2080aqds/README
+++ b/board/freescale/ls2080aqds/README
@@ -7,48 +7,9 @@
 a complete debugging environment.
 
 LS2080A SoC Overview
-------------------
-The LS2080A integrated multicore processor combines eight ARM Cortex-A57
-processor cores with high-performance data path acceleration logic and network
-and peripheral bus interfaces required for networking, telecom/datacom,
-wireless infrastructure, and mil/aerospace applications.
-
-The LS2080A SoC includes the following function and features:
-
- - Eight 64-bit ARM Cortex-A57 CPUs
- - 1 MB platform cache with ECC
- - Two 64-bit DDR4 SDRAM memory controllers with ECC and interleaving support
- - One secondary 32-bit DDR4 SDRAM memory controller, intended for use by
-  the AIOP
- - Data path acceleration architecture (DPAA2) incorporating acceleration for
- the following functions:
-   - Packet parsing, classification, and distribution (WRIOP)
-   - Queue and Hardware buffer management for scheduling, packet sequencing, and
-     congestion management, buffer allocation and de-allocation (QBMan)
-   - Cryptography acceleration (SEC) at up to 10 Gbps
-   - RegEx pattern matching acceleration (PME) at up to 10 Gbps
-   - Decompression/compression acceleration (DCE) at up to 20 Gbps
-   - Accelerated I/O processing (AIOP) at up to 20 Gbps
-   - QDMA engine
- - 16 SerDes lanes at up to 10.3125 GHz
- - Ethernet interfaces
-   - Up to eight 10 Gbps Ethernet MACs
-   - Up to eight 1 / 2.5 Gbps Ethernet MACs
- - High-speed peripheral interfaces
-   - Four PCIe 3.0 controllers, one supporting SR-IOV
- - Additional peripheral interfaces
-   - Two serial ATA (SATA 3.0) controllers
-   - Two high-speed USB 3.0 controllers with integrated PHY
-   - Enhanced secure digital host controller (eSDXC/eMMC)
-   - Serial peripheral interface (SPI) controller
-   - Quad Serial Peripheral Interface (QSPI) Controller
-   - Four I2C controllers
-   - Two DUARTs
-   - Integrated flash controller (IFC 2.0) supporting NAND and NOR flash
- - Support for hardware virtualization and partitioning enforcement
- - QorIQ platform's trust architecture 3.0
- - Service processor (SP) provides pre-boot initialization and secure-boot
-  capabilities
+--------------------
+Please refer arch/arm/cpu/armv8/fsl-layerscape/doc/README.soc for LS2080A
+SoC overview.
 
  LS2080AQDS board Overview
  -----------------------
diff --git a/board/freescale/ls2080aqds/ddr.h b/board/freescale/ls2080aqds/ddr.h
index b76ea61..eba62c3 100644
--- a/board/freescale/ls2080aqds/ddr.h
+++ b/board/freescale/ls2080aqds/ddr.h
@@ -28,10 +28,10 @@
 	 *   num|  hi| rank|  clk| wrlvl |   wrlvl   |  wrlvl
 	 * ranks| mhz| GB  |adjst| start |   ctl2    |  ctl3
 	 */
-	{2,  1350, 0, 4,     6, 0x0708090B, 0x0C0D0E09,},
-	{2,  1666, 0, 4,     7, 0x08090A0C, 0x0D0F100B,},
-	{2,  1900, 0, 4,     7, 0x09090B0D, 0x0E10120B,},
-	{2,  2300, 0, 4,     8, 0x090A0C0F, 0x1012130C,},
+	{2,  1350, 0, 8,     6, 0x0708090B, 0x0C0D0E09,},
+	{2,  1666, 0, 8,     7, 0x08090A0C, 0x0D0F100B,},
+	{2,  1900, 0, 8,     7, 0x09090B0D, 0x0E10120B,},
+	{2,  2300, 0, 8,     8, 0x090A0C0F, 0x1012130C,},
 	{}
 };
 
@@ -42,10 +42,10 @@
 	 *   num|  hi| rank|  clk| wrlvl |   wrlvl   |  wrlvl
 	 * ranks| mhz| GB  |adjst| start |   ctl2    |  ctl3
 	 */
-	{2,  1350, 0, 4,   0xd, 0x0C0A0A00, 0x00000009,},
-	{2,  1666, 0, 4,   0xd, 0x0C0A0A00, 0x00000009,},
-	{2,  1900, 0, 4,   0xe, 0x0D0C0B00, 0x0000000A,},
-	{2,  2200, 0, 4,   0xe, 0x0D0C0B00, 0x0000000A,},
+	{2,  1350, 0, 8,   0xd, 0x0C0A0A00, 0x00000009,},
+	{2,  1666, 0, 8,   0xd, 0x0C0A0A00, 0x00000009,},
+	{2,  1900, 0, 8,   0xe, 0x0D0C0B00, 0x0000000A,},
+	{2,  2200, 0, 8,   0xe, 0x0D0C0B00, 0x0000000A,},
 	{}
 };
 
@@ -55,10 +55,10 @@
 	 *   num|  hi| rank|  clk| wrlvl |   wrlvl   |  wrlvl
 	 * ranks| mhz| GB  |adjst| start |   ctl2    |  ctl3
 	 */
-	{2,  1350, 0, 4,     6, 0x0708090B, 0x0C0D0E09,},
-	{2,  1666, 0, 4,     7, 0x08090A0C, 0x0D0F100B,},
-	{2,  1900, 0, 4,     7, 0x09090B0D, 0x0E10120B,},
-	{2,  2200, 0, 4,     8, 0x090A0C0F, 0x1012130C,},
+	{2,  1350, 0, 8,     6, 0x0708090B, 0x0C0D0E09,},
+	{2,  1666, 0, 8,     7, 0x08090A0C, 0x0D0F100B,},
+	{2,  1900, 0, 8,     7, 0x09090B0D, 0x0E10120B,},
+	{2,  2200, 0, 8,     8, 0x090A0C0F, 0x1012130C,},
 	{}
 };
 
@@ -69,10 +69,10 @@
 	 *   num|  hi| rank|  clk| wrlvl |   wrlvl   |  wrlvl
 	 * ranks| mhz| GB  |adjst| start |   ctl2    |  ctl3
 	 */
-	{2,  1350, 0, 4,     6, 0x0708090B, 0x0C0D0E09,},
-	{2,  1666, 0, 4,     7, 0x0B0A090C, 0x0D0F100B,},
-	{2,  1900, 0, 4,     7, 0x09090B0D, 0x0E10120B,},
-	{2,  2200, 0, 4,     8, 0x090A0C0F, 0x1012130C,},
+	{2,  1350, 0, 8,     6, 0x0708090B, 0x0C0D0E09,},
+	{2,  1666, 0, 8,     7, 0x0B0A090C, 0x0D0F100B,},
+	{2,  1900, 0, 8,     7, 0x09090B0D, 0x0E10120B,},
+	{2,  2200, 0, 8,     8, 0x090A0C0F, 0x1012130C,},
 	{}
 };
 
diff --git a/board/freescale/ls2080aqds/ls2080aqds.c b/board/freescale/ls2080aqds/ls2080aqds.c
index b3bd40a..897793d 100644
--- a/board/freescale/ls2080aqds/ls2080aqds.c
+++ b/board/freescale/ls2080aqds/ls2080aqds.c
@@ -282,7 +282,9 @@
 #ifdef CONFIG_OF_BOARD_SETUP
 int ft_board_setup(void *blob, bd_t *bd)
 {
+#ifdef CONFIG_FSL_MC_ENET
 	int err;
+#endif
 	u64 base[CONFIG_NR_DRAM_BANKS];
 	u64 size[CONFIG_NR_DRAM_BANKS];
 
diff --git a/board/freescale/ls2080ardb/README b/board/freescale/ls2080ardb/README
index 6708ca9..b1613ba 100644
--- a/board/freescale/ls2080ardb/README
+++ b/board/freescale/ls2080ardb/README
@@ -5,48 +5,9 @@
 Layerscape Architecture processor.
 
 LS2080A SoC Overview
-------------------
-The LS2080A integrated multicore processor combines eight ARM Cortex-A57
-processor cores with high-performance data path acceleration logic and network
-and peripheral bus interfaces required for networking, telecom/datacom,
-wireless infrastructure, and mil/aerospace applications.
-
-The LS2080A SoC includes the following function and features:
-
- - Eight 64-bit ARM Cortex-A57 CPUs
- - 1 MB platform cache with ECC
- - Two 64-bit DDR4 SDRAM memory controllers with ECC and interleaving support
- - One secondary 32-bit DDR4 SDRAM memory controller, intended for use by
-  the AIOP
- - Data path acceleration architecture (DPAA2) incorporating acceleration for
- the following functions:
-   - Packet parsing, classification, and distribution (WRIOP)
-   - Queue and Hardware buffer management for scheduling, packet sequencing, and
-     congestion management, buffer allocation and de-allocation (QBMan)
-   - Cryptography acceleration (SEC) at up to 10 Gbps
-   - RegEx pattern matching acceleration (PME) at up to 10 Gbps
-   - Decompression/compression acceleration (DCE) at up to 20 Gbps
-   - Accelerated I/O processing (AIOP) at up to 20 Gbps
-   - QDMA engine
- - 16 SerDes lanes at up to 10.3125 GHz
- - Ethernet interfaces
-   - Up to eight 10 Gbps Ethernet MACs
-   - Up to eight 1 / 2.5 Gbps Ethernet MACs
- - High-speed peripheral interfaces
-   - Four PCIe 3.0 controllers, one supporting SR-IOV
- - Additional peripheral interfaces
-   - Two serial ATA (SATA 3.0) controllers
-   - Two high-speed USB 3.0 controllers with integrated PHY
-   - Enhanced secure digital host controller (eSDXC/eMMC)
-   - Serial peripheral interface (SPI) controller
-   - Quad Serial Peripheral Interface (QSPI) Controller
-   - Four I2C controllers
-   - Two DUARTs
-   - Integrated flash controller (IFC 2.0) supporting NAND and NOR flash
- - Support for hardware virtualization and partitioning enforcement
- - QorIQ platform's trust architecture 3.0
- - Service processor (SP) provides pre-boot initialization and secure-boot
-  capabilities
+--------------------
+Please refer arch/arm/cpu/armv8/fsl-layerscape/doc/README.soc for LS2080A
+SoC overview.
 
  LS2080ARDB board Overview
  -----------------------
diff --git a/board/freescale/ls2080ardb/ddr.h b/board/freescale/ls2080ardb/ddr.h
index b3c6306..8d5a490 100644
--- a/board/freescale/ls2080ardb/ddr.h
+++ b/board/freescale/ls2080ardb/ddr.h
@@ -28,10 +28,10 @@
 	 *   num|  hi| rank|  clk| wrlvl |   wrlvl   |  wrlvl
 	 * ranks| mhz| GB  |adjst| start |   ctl2    |  ctl3
 	 */
-	{2,  1350, 0, 4,     6, 0x0708090B, 0x0C0D0E09,},
-	{2,  1666, 0, 5,     9, 0x090A0B0E, 0x0F11110C,},
-	{2,  1900, 0, 6,   0xA, 0x0B0C0E11, 0x1214140F,},
-	{2,  2300, 0, 6,   0xB, 0x0C0D0F12, 0x14161610,},
+	{2,  1350, 0, 8,     6, 0x0708090B, 0x0C0D0E09,},
+	{2,  1666, 0, 10,    9, 0x090A0B0E, 0x0F11110C,},
+	{2,  1900, 0, 12,  0xA, 0x0B0C0E11, 0x1214140F,},
+	{2,  2300, 0, 12,  0xB, 0x0C0D0F12, 0x14161610,},
 	{}
 };
 
@@ -42,10 +42,10 @@
 	 *   num|  hi| rank|  clk| wrlvl |   wrlvl   |  wrlvl
 	 * ranks| mhz| GB  |adjst| start |   ctl2    |  ctl3
 	 */
-	{2,  1350, 0, 4,   0xd, 0x0C0A0A00, 0x00000009,},
-	{2,  1666, 0, 4,   0xd, 0x0C0A0A00, 0x00000009,},
-	{2,  1900, 0, 4,   0xe, 0x0D0C0B00, 0x0000000A,},
-	{2,  2200, 0, 4,   0xe, 0x0D0C0B00, 0x0000000A,},
+	{2,  1350, 0, 8,   0xd, 0x0C0A0A00, 0x00000009,},
+	{2,  1666, 0, 8,   0xd, 0x0C0A0A00, 0x00000009,},
+	{2,  1900, 0, 8,   0xe, 0x0D0C0B00, 0x0000000A,},
+	{2,  2200, 0, 8,   0xe, 0x0D0C0B00, 0x0000000A,},
 	{}
 };
 
@@ -55,10 +55,10 @@
 	 *   num|  hi| rank|  clk| wrlvl |   wrlvl   |  wrlvl
 	 * ranks| mhz| GB  |adjst| start |   ctl2    |  ctl3
 	 */
-	{2,  1350, 0, 4,     6, 0x0708090B, 0x0C0D0E09,},
-	{2,  1666, 0, 4,     7, 0x08090A0C, 0x0D0F100B,},
-	{2,  1900, 0, 4,     7, 0x09090B0D, 0x0E10120B,},
-	{2,  2200, 0, 4,     8, 0x090A0C0F, 0x1012130C,},
+	{2,  1350, 0, 8,     6, 0x0708090B, 0x0C0D0E09,},
+	{2,  1666, 0, 8,     7, 0x08090A0C, 0x0D0F100B,},
+	{2,  1900, 0, 8,     7, 0x09090B0D, 0x0E10120B,},
+	{2,  2200, 0, 8,     8, 0x090A0C0F, 0x1012130C,},
 	{}
 };
 
@@ -69,10 +69,10 @@
 	 *   num|  hi| rank|  clk| wrlvl |   wrlvl   |  wrlvl
 	 * ranks| mhz| GB  |adjst| start |   ctl2    |  ctl3
 	 */
-	{2,  1350, 0, 4,     6, 0x0708090B, 0x0C0D0E09,},
-	{2,  1666, 0, 4,     7, 0x0B0A090C, 0x0D0F100B,},
-	{2,  1900, 0, 4,     7, 0x09090B0D, 0x0E10120B,},
-	{2,  2200, 0, 4,     8, 0x090A0C0F, 0x1012130C,},
+	{2,  1350, 0, 8,     6, 0x0708090B, 0x0C0D0E09,},
+	{2,  1666, 0, 8,     7, 0x0B0A090C, 0x0D0F100B,},
+	{2,  1900, 0, 8,     7, 0x09090B0D, 0x0E10120B,},
+	{2,  2200, 0, 8,     8, 0x090A0C0F, 0x1012130C,},
 	{}
 };
 
diff --git a/board/freescale/ls2080ardb/ls2080ardb.c b/board/freescale/ls2080ardb/ls2080ardb.c
index fb39af6..52e5e3f 100644
--- a/board/freescale/ls2080ardb/ls2080ardb.c
+++ b/board/freescale/ls2080ardb/ls2080ardb.c
@@ -156,7 +156,9 @@
 {
 	char *env_hwconfig;
 	u32 __iomem *dcfg_ccsr = (u32 __iomem *)DCFG_BASE;
+#ifdef CONFIG_FSL_MC_ENET
 	u32 __iomem *irq_ccsr = (u32 __iomem *)ISC_BASE;
+#endif
 	u32 val;
 
 	init_final_memctl_regs();
@@ -178,8 +180,10 @@
 
 	QIXIS_WRITE(rst_ctl, QIXIS_RST_CTL_RESET_EN);
 
+#ifdef CONFIG_FSL_MC_ENET
 	/* invert AQR405 IRQ pins polarity */
 	out_le32(irq_ccsr + IRQCR_OFFSET / 4, AQR405_IRQ_MASK);
+#endif
 
 	return 0;
 }
@@ -261,7 +265,9 @@
 #ifdef CONFIG_OF_BOARD_SETUP
 int ft_board_setup(void *blob, bd_t *bd)
 {
+#ifdef CONFIG_FSL_MC_ENET
 	int err;
+#endif
 	u64 base[CONFIG_NR_DRAM_BANKS];
 	u64 size[CONFIG_NR_DRAM_BANKS];
 
diff --git a/board/freescale/m5329evb/nand.c b/board/freescale/m5329evb/nand.c
index 8d88bc0..8849681 100644
--- a/board/freescale/m5329evb/nand.c
+++ b/board/freescale/m5329evb/nand.c
@@ -24,7 +24,7 @@
 
 static void nand_hwcontrol(struct mtd_info *mtdinfo, int cmd, unsigned int ctrl)
 {
-	struct nand_chip *this = mtdinfo->priv;
+	struct nand_chip *this = mtd_to_nand(mtdinfo);
 	volatile u16 *nCE = (u16 *) CONFIG_SYS_LATCH_ADDR;
 
 	if (ctrl & NAND_CTRL_CHANGE) {
diff --git a/board/freescale/m5373evb/nand.c b/board/freescale/m5373evb/nand.c
index 92cef2a..a96a599 100644
--- a/board/freescale/m5373evb/nand.c
+++ b/board/freescale/m5373evb/nand.c
@@ -24,7 +24,7 @@
 
 static void nand_hwcontrol(struct mtd_info *mtdinfo, int cmd, unsigned int ctrl)
 {
-	struct nand_chip *this = mtdinfo->priv;
+	struct nand_chip *this = mtd_to_nand(mtdinfo);
 	volatile u16 *nCE = (u16 *) CONFIG_SYS_LATCH_ADDR;
 
 	if (ctrl & NAND_CTRL_CHANGE) {
diff --git a/board/freescale/p1010rdb/Makefile b/board/freescale/p1010rdb/Makefile
index 660d1bb..86eb694 100644
--- a/board/freescale/p1010rdb/Makefile
+++ b/board/freescale/p1010rdb/Makefile
@@ -13,18 +13,14 @@
 endif
 
 ifdef MINIMAL
-
-obj-y	+= spl_minimal.o tlb.o law.o
-
+obj-y	+= spl_minimal.o
 else
-
 ifdef CONFIG_SPL_BUILD
-obj-y += spl.o
+obj-y	+= spl.o
 endif
-
 obj-y	+= p1010rdb.o
 obj-y	+= ddr.o
+endif
+
 obj-y	+= law.o
 obj-y	+= tlb.o
-
-endif
diff --git a/board/freescale/p1010rdb/spl.c b/board/freescale/p1010rdb/spl.c
index eb8e567..f858408 100644
--- a/board/freescale/p1010rdb/spl.c
+++ b/board/freescale/p1010rdb/spl.c
@@ -72,6 +72,7 @@
 	get_clocks();
 	mem_malloc_init(CONFIG_SPL_RELOC_MALLOC_ADDR,
 			CONFIG_SPL_RELOC_MALLOC_SIZE);
+	gd->flags |= GD_FLG_FULL_MALLOC_INIT;
 
 #ifndef CONFIG_SPL_NAND_BOOT
 	env_init();
diff --git a/board/freescale/p1022ds/Makefile b/board/freescale/p1022ds/Makefile
index a582127..9793853 100644
--- a/board/freescale/p1022ds/Makefile
+++ b/board/freescale/p1022ds/Makefile
@@ -13,17 +13,15 @@
 endif
 
 ifdef MINIMAL
-
-obj-y        += spl_minimal.o tlb.o law.o
-
+obj-y	+= spl_minimal.o
 else
 ifdef CONFIG_SPL_BUILD
-obj-y += spl.o
+obj-y	+= spl.o
 endif
 obj-y	+= p1022ds.o
 obj-y	+= ddr.o
-obj-y	+= law.o
-obj-y	+= tlb.o
-
 obj-$(CONFIG_FSL_DIU_FB) += diu.o
 endif
+
+obj-y	+= law.o
+obj-y	+= tlb.o
diff --git a/board/freescale/p1022ds/spl.c b/board/freescale/p1022ds/spl.c
index 89ef95a..04db767 100644
--- a/board/freescale/p1022ds/spl.c
+++ b/board/freescale/p1022ds/spl.c
@@ -86,6 +86,7 @@
 	get_clocks();
 	mem_malloc_init(CONFIG_SPL_RELOC_MALLOC_ADDR,
 			CONFIG_SPL_RELOC_MALLOC_SIZE);
+	gd->flags |= GD_FLG_FULL_MALLOC_INIT;
 #ifndef CONFIG_SPL_NAND_BOOT
 	env_init();
 #endif
diff --git a/board/freescale/p1_p2_rdb_pc/Makefile b/board/freescale/p1_p2_rdb_pc/Makefile
index a2a1f92..045d409 100644
--- a/board/freescale/p1_p2_rdb_pc/Makefile
+++ b/board/freescale/p1_p2_rdb_pc/Makefile
@@ -13,17 +13,14 @@
 endif
 
 ifdef MINIMAL
-
-obj-y	+= spl_minimal.o tlb.o law.o
-
+obj-y	+= spl_minimal.o
 else
 ifdef CONFIG_SPL_BUILD
-obj-y += spl.o
+obj-y	+= spl.o
 endif
-
-obj-y        += p1_p2_rdb_pc.o
-obj-y        += ddr.o
-obj-y        += law.o
-obj-y        += tlb.o
-
+obj-y	+= p1_p2_rdb_pc.o
+obj-y	+= ddr.o
 endif
+
+obj-y	+= law.o
+obj-y	+= tlb.o
diff --git a/board/freescale/p1_p2_rdb_pc/spl.c b/board/freescale/p1_p2_rdb_pc/spl.c
index 0142746..76a3cf4 100644
--- a/board/freescale/p1_p2_rdb_pc/spl.c
+++ b/board/freescale/p1_p2_rdb_pc/spl.c
@@ -83,6 +83,7 @@
 	get_clocks();
 	mem_malloc_init(CONFIG_SPL_RELOC_MALLOC_ADDR,
 			CONFIG_SPL_RELOC_MALLOC_SIZE);
+	gd->flags |= GD_FLG_FULL_MALLOC_INIT;
 
 #ifndef CONFIG_SPL_NAND_BOOT
 	env_init();
diff --git a/board/freescale/p2041rdb/Makefile b/board/freescale/p2041rdb/Makefile
index c74f4c6..a335ec6 100644
--- a/board/freescale/p2041rdb/Makefile
+++ b/board/freescale/p2041rdb/Makefile
@@ -7,6 +7,6 @@
 #
 
 obj-y	+= p2041rdb.o
-obj-y += cpld.o
+obj-y	+= cpld.o
 obj-y	+= ddr.o
 obj-y	+= eth.o
diff --git a/board/freescale/t102xqds/Makefile b/board/freescale/t102xqds/Makefile
index d94f230..afbc914 100644
--- a/board/freescale/t102xqds/Makefile
+++ b/board/freescale/t102xqds/Makefile
@@ -5,7 +5,7 @@
 #
 
 ifdef CONFIG_SPL_BUILD
-obj-y += spl.o
+obj-y	+= spl.o
 else
 obj-y	+= t102xqds.o
 obj-y	+= eth_t102xqds.o
diff --git a/board/freescale/t102xqds/ddr.c b/board/freescale/t102xqds/ddr.c
index 2d4d10f..c26f350 100644
--- a/board/freescale/t102xqds/ddr.c
+++ b/board/freescale/t102xqds/ddr.c
@@ -35,18 +35,18 @@
 	 * ranks| mhz| GB  |adjst| start |   ctl2    |  ctl3  |
 	 */
 #if defined(CONFIG_SYS_FSL_DDR4)
-	{2,  1666,  0,  4,  7,  0x0808090B,  0x0C0D0E0A,},
-	{2,  1900,  0,  4,  6,  0x08080A0C,  0x0D0E0F0A,},
-	{1,  1666,  0,  4,  6,  0x0708090B,  0x0C0D0E09,},
-	{1,  1900,  0,  4,  6,  0x08080A0C,  0x0D0E0F0A,},
-	{1,  2200,  0,  4,  7,  0x08090A0D,  0x0F0F100C,},
+	{2,  1666,  0,  8,  7,  0x0808090B,  0x0C0D0E0A,},
+	{2,  1900,  0,  8,  6,  0x08080A0C,  0x0D0E0F0A,},
+	{1,  1666,  0,  8,  6,  0x0708090B,  0x0C0D0E09,},
+	{1,  1900,  0,  8,  6,  0x08080A0C,  0x0D0E0F0A,},
+	{1,  2200,  0,  8,  7,  0x08090A0D,  0x0F0F100C,},
 #elif defined(CONFIG_SYS_FSL_DDR3)
-	{2,  833,   0,  4,  6,  0x06060607,  0x08080807,},
-	{2,  1350,  0,  4,  7,  0x0708080A,  0x0A0B0C09,},
-	{2,  1666,  0,  4,  7,  0x0808090B,  0x0C0D0E0A,},
-	{1,  833,   0,  4,  6,  0x06060607,  0x08080807,},
-	{1,  1350,  0,  4,  7,  0x0708080A,  0x0A0B0C09,},
-	{1,  1666,  0,  4,  7,  0x0808090B,  0x0C0D0E0A,},
+	{2,  833,   0,  8,  6,  0x06060607,  0x08080807,},
+	{2,  1350,  0,  8,  7,  0x0708080A,  0x0A0B0C09,},
+	{2,  1666,  0,  8,  7,  0x0808090B,  0x0C0D0E0A,},
+	{1,  833,   0,  8,  6,  0x06060607,  0x08080807,},
+	{1,  1350,  0,  8,  7,  0x0708080A,  0x0A0B0C09,},
+	{1,  1666,  0,  8,  7,  0x0808090B,  0x0C0D0E0A,},
 #else
 #error DDR type not defined
 #endif
@@ -172,14 +172,13 @@
 
 #if defined(CONFIG_SPL_BUILD) || !defined(CONFIG_RAMBOOT_PBL)
 	puts("Initializing....using SPD\n");
-
 	dram_size = fsl_ddr_sdram();
-	dram_size = setup_ddr_tlbs(dram_size / 0x100000);
-	dram_size *= 0x100000;
 #else
 	/* DDR has been initialised by first stage boot loader */
 	dram_size =  fsl_ddr_sdram_size();
 #endif
+	dram_size = setup_ddr_tlbs(dram_size / 0x100000);
+	dram_size *= 0x100000;
 
 #if defined(CONFIG_DEEP_SLEEP) && !defined(CONFIG_SPL_BUILD)
 	fsl_dp_resume();
diff --git a/board/freescale/t102xqds/spl.c b/board/freescale/t102xqds/spl.c
index 073ff2d..d59d343 100644
--- a/board/freescale/t102xqds/spl.c
+++ b/board/freescale/t102xqds/spl.c
@@ -120,6 +120,7 @@
 	get_clocks();
 	mem_malloc_init(CONFIG_SPL_RELOC_MALLOC_ADDR,
 			CONFIG_SPL_RELOC_MALLOC_SIZE);
+	gd->flags |= GD_FLG_FULL_MALLOC_INIT;
 
 #ifdef CONFIG_SPL_NAND_BOOT
 	nand_spl_load_image(CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE,
diff --git a/board/freescale/t102xrdb/Makefile b/board/freescale/t102xrdb/Makefile
index 0520066..6452865 100644
--- a/board/freescale/t102xrdb/Makefile
+++ b/board/freescale/t102xrdb/Makefile
@@ -5,7 +5,7 @@
 #
 
 ifdef CONFIG_SPL_BUILD
-obj-y += spl.o
+obj-y	+= spl.o
 else
 obj-y   += t102xrdb.o
 obj-$(CONFIG_T1024RDB)   += cpld.o
diff --git a/board/freescale/t102xrdb/ddr.c b/board/freescale/t102xrdb/ddr.c
index adf9fd5..edfbdbf 100644
--- a/board/freescale/t102xrdb/ddr.c
+++ b/board/freescale/t102xrdb/ddr.c
@@ -34,12 +34,12 @@
 	 *   num|  hi| rank|  clk| wrlvl |   wrlvl   |  wrlvl |
 	 * ranks| mhz| GB  |adjst| start |   ctl2    |  ctl3  |
 	 */
-	{2,  833,   0,  4,  6,  0x06060607,  0x08080807,},
-	{2,  1350,  0,  4,  7,  0x0708080A,  0x0A0B0C09,},
-	{2,  1666,  0,  4,  7,  0x0808090B,  0x0C0D0E0A,},
-	{1,  833,   0,  4,  6,  0x06060607,  0x08080807,},
-	{1,  1350,  0,  4,  7,  0x0708080A,  0x0A0B0C09,},
-	{1,  1666,  0,  4,  7,  0x0808090B,  0x0C0D0E0A,},
+	{2,  833,   0,  8,  6,  0x06060607,  0x08080807,},
+	{2,  1350,  0,  8,  7,  0x0708080A,  0x0A0B0C09,},
+	{2,  1666,  0,  8,  7,  0x0808090B,  0x0C0D0E0A,},
+	{1,  833,   0,  8,  6,  0x06060607,  0x08080807,},
+	{1,  1350,  0,  8,  7,  0x0708080A,  0x0A0B0C09,},
+	{1,  1666,  0,  8,  7,  0x0808090B,  0x0C0D0E0A,},
 	{}
 };
 
@@ -234,12 +234,12 @@
 	puts("Initializing....using SPD\n");
 #endif
 	dram_size = fsl_ddr_sdram();
-	dram_size = setup_ddr_tlbs(dram_size / 0x100000);
-	dram_size *= 0x100000;
 #else
 	/* DDR has been initialised by first stage boot loader */
 	dram_size =  fsl_ddr_sdram_size();
 #endif
+	dram_size = setup_ddr_tlbs(dram_size / 0x100000);
+	dram_size *= 0x100000;
 
 #if defined(CONFIG_DEEP_SLEEP) && !defined(CONFIG_SPL_BUILD)
 	fsl_dp_resume();
diff --git a/board/freescale/t102xrdb/spl.c b/board/freescale/t102xrdb/spl.c
index da97c44..bd3cbbf 100644
--- a/board/freescale/t102xrdb/spl.c
+++ b/board/freescale/t102xrdb/spl.c
@@ -107,6 +107,7 @@
 	get_clocks();
 	mem_malloc_init(CONFIG_SPL_RELOC_MALLOC_ADDR,
 			CONFIG_SPL_RELOC_MALLOC_SIZE);
+	gd->flags |= GD_FLG_FULL_MALLOC_INIT;
 
 #ifdef CONFIG_SPL_NAND_BOOT
 	nand_spl_load_image(CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE,
diff --git a/board/freescale/t1040qds/ddr.h b/board/freescale/t1040qds/ddr.h
index a6e1673..1e08746 100644
--- a/board/freescale/t1040qds/ddr.h
+++ b/board/freescale/t1040qds/ddr.h
@@ -29,18 +29,18 @@
 	 * ranks| mhz| GB  |adjst| start |   ctl2    |  ctl3  |
 	 */
 #ifdef CONFIG_SYS_FSL_DDR4
-	{2,  1666, 0, 4,     7, 0x0808090B, 0x0C0D0E0A,},
-	{2,  1900, 0, 4,     6, 0x08080A0C, 0x0D0E0F0A,},
-	{1,  1666, 0, 4,     6, 0x0708090B, 0x0C0D0E09,},
-	{1,  1900, 0, 4,     6, 0x08080A0C, 0x0D0E0F0A,},
-	{1,  2200, 0, 4,     7, 0x08090A0D, 0x0F0F100C,},
+	{2,  1666, 0, 8,     7, 0x0808090B, 0x0C0D0E0A,},
+	{2,  1900, 0, 8,     6, 0x08080A0C, 0x0D0E0F0A,},
+	{1,  1666, 0, 8,     6, 0x0708090B, 0x0C0D0E09,},
+	{1,  1900, 0, 8,     6, 0x08080A0C, 0x0D0E0F0A,},
+	{1,  2200, 0, 8,     7, 0x08090A0D, 0x0F0F100C,},
 #elif defined(CONFIG_SYS_FSL_DDR3)
-	{2,  833,  0, 4,     6, 0x06060607, 0x08080807,},
-	{2,  1350, 0, 4,     7, 0x0708080A, 0x0A0B0C09,},
-	{2,  1666, 0, 4,     7, 0x0808090B, 0x0C0D0E0A,},
-	{1,  833,  0, 4,     6, 0x06060607, 0x08080807,},
-	{1,  1350, 0, 4,     7, 0x0708080A, 0x0A0B0C09,},
-	{1,  1666, 0, 4,     7, 0x0808090B, 0x0C0D0E0A,},
+	{2,  833,  0, 8,     6, 0x06060607, 0x08080807,},
+	{2,  1350, 0, 8,     7, 0x0708080A, 0x0A0B0C09,},
+	{2,  1666, 0, 8,     7, 0x0808090B, 0x0C0D0E0A,},
+	{1,  833,  0, 8,     6, 0x06060607, 0x08080807,},
+	{1,  1350, 0, 8,     7, 0x0708080A, 0x0A0B0C09,},
+	{1,  1666, 0, 8,     7, 0x0808090B, 0x0C0D0E0A,},
 #else
 #error DDR type not defined
 #endif
diff --git a/board/freescale/t104xrdb/ddr.c b/board/freescale/t104xrdb/ddr.c
index cf79d2d..22d6a5f 100644
--- a/board/freescale/t104xrdb/ddr.c
+++ b/board/freescale/t104xrdb/ddr.c
@@ -124,15 +124,12 @@
 
 #if defined(CONFIG_SPL_BUILD) || !defined(CONFIG_RAMBOOT_PBL)
 	puts("Initializing....using SPD\n");
-
 	dram_size = fsl_ddr_sdram();
-
-	dram_size = setup_ddr_tlbs(dram_size / 0x100000);
-	dram_size *= 0x100000;
-
 #else
 	dram_size =  fsl_ddr_sdram_size();
 #endif
+	dram_size = setup_ddr_tlbs(dram_size / 0x100000);
+	dram_size *= 0x100000;
 
 #if defined(CONFIG_DEEP_SLEEP) && !defined(CONFIG_SPL_BUILD)
 	fsl_dp_resume();
diff --git a/board/freescale/t104xrdb/ddr.h b/board/freescale/t104xrdb/ddr.h
index b9c02f7..012991c 100644
--- a/board/freescale/t104xrdb/ddr.h
+++ b/board/freescale/t104xrdb/ddr.h
@@ -29,20 +29,20 @@
 	 * ranks| mhz| GB  |adjst| start |   ctl2
 	 */
 #ifdef CONFIG_SYS_FSL_DDR4
-	{2,  1600, 4, 4,     6, 0x07090A0c, 0x0e0f100a},
+	{2,  1600, 4, 8,     6, 0x07090A0c, 0x0e0f100a},
 #elif defined(CONFIG_SYS_FSL_DDR3)
-	{2,  833,  4, 4,     6, 0x06060607, 0x08080807},
-	{2,  833,  0, 4,     6, 0x06060607, 0x08080807},
-	{2,  1350, 4, 4,     7, 0x0708080A, 0x0A0B0C09},
-	{2,  1350, 0, 4,     7, 0x0708080A, 0x0A0B0C09},
-	{2,  1666, 4, 4,     7, 0x0808090B, 0x0C0D0E0A},
-	{2,  1666, 0, 4,     7, 0x0808090B, 0x0C0D0E0A},
-	{1,  833,  4, 4,     6, 0x06060607, 0x08080807},
-	{1,  833,  0, 4,     6, 0x06060607, 0x08080807},
-	{1,  1350, 4, 4,     7, 0x0708080A, 0x0A0B0C09},
-	{1,  1350, 0, 4,     7, 0x0708080A, 0x0A0B0C09},
-	{1,  1666, 4, 4,     7, 0x0808090B, 0x0C0D0E0A},
-	{1,  1666, 0, 4,     7, 0x0808090B, 0x0C0D0E0A},
+	{2,  833,  4, 8,     6, 0x06060607, 0x08080807},
+	{2,  833,  0, 8,     6, 0x06060607, 0x08080807},
+	{2,  1350, 4, 8,     7, 0x0708080A, 0x0A0B0C09},
+	{2,  1350, 0, 8,     7, 0x0708080A, 0x0A0B0C09},
+	{2,  1666, 4, 8,     7, 0x0808090B, 0x0C0D0E0A},
+	{2,  1666, 0, 8,     7, 0x0808090B, 0x0C0D0E0A},
+	{1,  833,  4, 8,     6, 0x06060607, 0x08080807},
+	{1,  833,  0, 8,     6, 0x06060607, 0x08080807},
+	{1,  1350, 4, 8,     7, 0x0708080A, 0x0A0B0C09},
+	{1,  1350, 0, 8,     7, 0x0708080A, 0x0A0B0C09},
+	{1,  1666, 4, 8,     7, 0x0808090B, 0x0C0D0E0A},
+	{1,  1666, 0, 8,     7, 0x0808090B, 0x0C0D0E0A},
 #else
 #error DDR type not defined
 #endif
diff --git a/board/freescale/t104xrdb/spl.c b/board/freescale/t104xrdb/spl.c
index 81f48c4..4b35af6 100644
--- a/board/freescale/t104xrdb/spl.c
+++ b/board/freescale/t104xrdb/spl.c
@@ -98,6 +98,7 @@
 	get_clocks();
 	mem_malloc_init(CONFIG_SPL_RELOC_MALLOC_ADDR,
 			CONFIG_SPL_RELOC_MALLOC_SIZE);
+	gd->flags |= GD_FLG_FULL_MALLOC_INIT;
 
 #ifdef CONFIG_SPL_MMC_BOOT
 	mmc_initialize(bd);
diff --git a/board/freescale/t208xqds/Makefile b/board/freescale/t208xqds/Makefile
index 6cb72c9..ef04a26 100644
--- a/board/freescale/t208xqds/Makefile
+++ b/board/freescale/t208xqds/Makefile
@@ -7,10 +7,8 @@
 ifdef CONFIG_SPL_BUILD
 obj-y += spl.o
 else
-obj-$(CONFIG_T2080QDS) += t208xqds.o
-obj-$(CONFIG_T2080QDS) += eth_t208xqds.o
-obj-$(CONFIG_T2081QDS) += t208xqds.o
-obj-$(CONFIG_T2081QDS) += eth_t208xqds.o
+obj-$(CONFIG_T2080QDS) += t208xqds.o eth_t208xqds.o
+obj-$(CONFIG_T2081QDS) += t208xqds.o eth_t208xqds.o
 obj-$(CONFIG_PCI)      += pci.o
 endif
 
diff --git a/board/freescale/t208xqds/ddr.c b/board/freescale/t208xqds/ddr.c
index f1aff54..f96470f 100644
--- a/board/freescale/t208xqds/ddr.c
+++ b/board/freescale/t208xqds/ddr.c
@@ -108,13 +108,12 @@
 #if defined(CONFIG_SPL_BUILD) || !defined(CONFIG_RAMBOOT_PBL)
 	puts("Initializing....using SPD\n");
 	dram_size = fsl_ddr_sdram();
-
-	dram_size = setup_ddr_tlbs(dram_size / 0x100000);
-	dram_size *= 0x100000;
 #else
 	/* DDR has been initialised by first stage boot loader */
 	dram_size =  fsl_ddr_sdram_size();
 #endif
+	dram_size = setup_ddr_tlbs(dram_size / 0x100000);
+	dram_size *= 0x100000;
 
 	return dram_size;
 }
diff --git a/board/freescale/t208xqds/ddr.h b/board/freescale/t208xqds/ddr.h
index 9c26fdf..255ab2c 100644
--- a/board/freescale/t208xqds/ddr.h
+++ b/board/freescale/t208xqds/ddr.h
@@ -28,17 +28,17 @@
 	 *   num|  hi| rank|  clk| wrlvl | wrlvl | wrlvl |
 	 * ranks| mhz| GB  |adjst| start | ctl2  | ctl3  |
 	 */
-	{2,  1200,  0,  5,  7,  0x0708090a,  0x0b0c0d09},
-	{2,  1400,  0,  5,  7,  0x08090a0c,  0x0d0e0f0a},
-	{2,  1700,  0,  5,  8,  0x090a0b0c,  0x0e10110c},
-	{2,  1900,  0,  5,  8,  0x090b0c0f,  0x1012130d},
-	{2,  2140,  0,  5,  8,  0x090b0c0f,  0x1012130d},
-	{1,  1200,  0,  5,  7,  0x0808090a,  0x0b0c0c0a},
-	{1,  1500,  0,  5,  6,  0x07070809,  0x0a0b0b09},
-	{1,  1600,  0,  5,  8,  0x090b0b0d,  0x0d0e0f0b},
-	{1,  1700,  0,  4,  8,  0x080a0a0c,  0x0c0d0e0a},
-	{1,  1900,  0,  5,  8,  0x090a0c0d,  0x0e0f110c},
-	{1,  2140,  0,  4,  8,  0x090a0b0d,  0x0e0f110b},
+	{2,  1200,  0, 10,  7,  0x0708090a,  0x0b0c0d09},
+	{2,  1400,  0, 10,  7,  0x08090a0c,  0x0d0e0f0a},
+	{2,  1700,  0, 10,  8,  0x090a0b0c,  0x0e10110c},
+	{2,  1900,  0, 10,  8,  0x090b0c0f,  0x1012130d},
+	{2,  2140,  0, 10,  8,  0x090b0c0f,  0x1012130d},
+	{1,  1200,  0, 10,  7,  0x0808090a,  0x0b0c0c0a},
+	{1,  1500,  0, 10,  6,  0x07070809,  0x0a0b0b09},
+	{1,  1600,  0, 10,  8,  0x090b0b0d,  0x0d0e0f0b},
+	{1,  1700,  0,  8,  8,  0x080a0a0c,  0x0c0d0e0a},
+	{1,  1900,  0, 10,  8,  0x090a0c0d,  0x0e0f110c},
+	{1,  2140,  0,  8,  8,  0x090a0b0d,  0x0e0f110b},
 	{}
 };
 
@@ -49,15 +49,15 @@
 	 * ranks| mhz| GB  |adjst| start |   ctl2    |  ctl3  |
 	 */
 	/* TODO: need tuning these parameters if RDIMM is used */
-	{4,  1350, 0, 5,     9, 0x08070605, 0x06070806},
-	{4,  1666, 0, 5,    11, 0x0a080706, 0x07090906},
-	{4,  2140, 0, 5,    12, 0x0b090807, 0x080a0b07},
-	{2,  1350, 0, 5,     9, 0x08070605, 0x06070806},
-	{2,  1666, 0, 5,    11, 0x0a090806, 0x08090a06},
-	{2,  2140, 0, 5,    12, 0x0b090807, 0x080a0b07},
-	{1,  1350, 0, 5,     9, 0x08070605, 0x06070806},
-	{1,  1666, 0, 5,    11, 0x0a090806, 0x08090a06},
-	{1,  2140, 0, 4,    12, 0x0b090807, 0x080a0b07},
+	{4,  1350, 0, 10,     9, 0x08070605, 0x06070806},
+	{4,  1666, 0, 10,    11, 0x0a080706, 0x07090906},
+	{4,  2140, 0, 10,    12, 0x0b090807, 0x080a0b07},
+	{2,  1350, 0, 10,     9, 0x08070605, 0x06070806},
+	{2,  1666, 0, 10,    11, 0x0a090806, 0x08090a06},
+	{2,  2140, 0, 10,    12, 0x0b090807, 0x080a0b07},
+	{1,  1350, 0, 10,     9, 0x08070605, 0x06070806},
+	{1,  1666, 0, 10,    11, 0x0a090806, 0x08090a06},
+	{1,  2140, 0,  8,    12, 0x0b090807, 0x080a0b07},
 	{}
 };
 
diff --git a/board/freescale/t208xqds/spl.c b/board/freescale/t208xqds/spl.c
index 55a0f8f..bb02dab 100644
--- a/board/freescale/t208xqds/spl.c
+++ b/board/freescale/t208xqds/spl.c
@@ -106,6 +106,7 @@
 	get_clocks();
 	mem_malloc_init(CONFIG_SPL_RELOC_MALLOC_ADDR,
 			CONFIG_SPL_RELOC_MALLOC_SIZE);
+	gd->flags |= GD_FLG_FULL_MALLOC_INIT;
 
 #ifdef CONFIG_SPL_NAND_BOOT
 	nand_spl_load_image(CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE,
diff --git a/board/freescale/t208xrdb/Makefile b/board/freescale/t208xrdb/Makefile
index 9605f8b..cd8fe09 100644
--- a/board/freescale/t208xrdb/Makefile
+++ b/board/freescale/t208xrdb/Makefile
@@ -5,11 +5,9 @@
 #
 
 ifdef CONFIG_SPL_BUILD
-obj-y += spl.o
+obj-y	+= spl.o
 else
-obj-$(CONFIG_T2080RDB) += t208xrdb.o
-obj-$(CONFIG_T2080RDB) += eth_t208xrdb.o
-obj-$(CONFIG_T2080RDB) += cpld.o
+obj-$(CONFIG_T2080RDB) += t208xrdb.o eth_t208xrdb.o cpld.o
 obj-$(CONFIG_PCI)      += pci.o
 endif
 
diff --git a/board/freescale/t208xrdb/ddr.c b/board/freescale/t208xrdb/ddr.c
index 053f128..f6c8ca3 100644
--- a/board/freescale/t208xrdb/ddr.c
+++ b/board/freescale/t208xrdb/ddr.c
@@ -101,12 +101,12 @@
 #if defined(CONFIG_SPL_BUILD) || !defined(CONFIG_RAMBOOT_PBL)
 	puts("Initializing....using SPD\n");
 	dram_size = fsl_ddr_sdram();
-
-	dram_size = setup_ddr_tlbs(dram_size / 0x100000);
-	dram_size *= 0x100000;
 #else
 	/* DDR has been initialised by first stage boot loader */
 	dram_size = fsl_ddr_sdram_size();
 #endif
+	dram_size = setup_ddr_tlbs(dram_size / 0x100000);
+	dram_size *= 0x100000;
+
 	return dram_size;
 }
diff --git a/board/freescale/t208xrdb/ddr.h b/board/freescale/t208xrdb/ddr.h
index 08cbb60..175cf56 100644
--- a/board/freescale/t208xrdb/ddr.h
+++ b/board/freescale/t208xrdb/ddr.h
@@ -28,16 +28,16 @@
 	 *   num|  hi| rank|  clk| wrlvl |   wrlvl   |  wrlvl |
 	 * ranks| mhz| GB  |adjst| start |   ctl2    |  ctl3  |
 	 */
-	{2,  1200, 2, 5,     7, 0x0808090a, 0x0b0c0c0a},
-	{2,  1500, 2, 5,     6, 0x07070809, 0x0a0b0b09},
-	{2,  1600, 2, 5,     8, 0x0808070b, 0x0c0d0e0a},
-	{2,  1700, 2, 4,     7, 0x080a0a0c, 0x0c0d0e0a},
-	{2,  1900, 0, 5,     7, 0x0808080c, 0x0b0c0c09},
-	{1,  1200, 2, 5,     7, 0x0808090a, 0x0b0c0c0a},
-	{1,  1500, 2, 5,     6, 0x07070809, 0x0a0b0b09},
-	{1,  1600, 2, 5,     8, 0x0808070b, 0x0c0d0e0a},
-	{1,  1700, 2, 4,     7, 0x080a0a0c, 0x0c0d0e0a},
-	{1,  1900, 0, 5,     7, 0x0808080c, 0x0b0c0c09},
+	{2,  1200, 2, 10,     7, 0x0808090a, 0x0b0c0c0a},
+	{2,  1500, 2, 10,     6, 0x07070809, 0x0a0b0b09},
+	{2,  1600, 2, 10,     8, 0x0808070b, 0x0c0d0e0a},
+	{2,  1700, 2,  8,     7, 0x080a0a0c, 0x0c0d0e0a},
+	{2,  1900, 0, 10,     7, 0x0808080c, 0x0b0c0c09},
+	{1,  1200, 2, 10,     7, 0x0808090a, 0x0b0c0c0a},
+	{1,  1500, 2, 10,     6, 0x07070809, 0x0a0b0b09},
+	{1,  1600, 2, 10,     8, 0x0808070b, 0x0c0d0e0a},
+	{1,  1700, 2,  8,     7, 0x080a0a0c, 0x0c0d0e0a},
+	{1,  1900, 0, 10,     7, 0x0808080c, 0x0b0c0c09},
 	{}
 };
 
diff --git a/board/freescale/t208xrdb/spl.c b/board/freescale/t208xrdb/spl.c
index f63366b..2ff05a2 100644
--- a/board/freescale/t208xrdb/spl.c
+++ b/board/freescale/t208xrdb/spl.c
@@ -76,6 +76,7 @@
 	get_clocks();
 	mem_malloc_init(CONFIG_SPL_RELOC_MALLOC_ADDR,
 			CONFIG_SPL_RELOC_MALLOC_SIZE);
+	gd->flags |= GD_FLG_FULL_MALLOC_INIT;
 
 #ifdef CONFIG_SPL_NAND_BOOT
 	nand_spl_load_image(CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE,
diff --git a/board/freescale/t4qds/Makefile b/board/freescale/t4qds/Makefile
index bd2c1f1..731ccb0 100644
--- a/board/freescale/t4qds/Makefile
+++ b/board/freescale/t4qds/Makefile
@@ -5,12 +5,12 @@
 #
 
 ifdef CONFIG_SPL_BUILD
-obj-y += spl.o
+obj-y	+= spl.o
 else
-obj-$(CONFIG_T4240QDS) += t4240qds.o
-obj-$(CONFIG_T4240QDS)+= eth.o
+obj-$(CONFIG_T4240QDS)	+= t4240qds.o eth.o
 obj-$(CONFIG_PCI)	+= pci.o
 endif
+
 obj-y	+= ddr.o
 obj-y	+= law.o
 obj-y	+= tlb.o
diff --git a/board/freescale/t4qds/ddr.c b/board/freescale/t4qds/ddr.c
index 62d58c5..d533924 100644
--- a/board/freescale/t4qds/ddr.c
+++ b/board/freescale/t4qds/ddr.c
@@ -117,13 +117,12 @@
 
 #if defined(CONFIG_SPL_BUILD) || !defined(CONFIG_RAMBOOT_PBL)
 	dram_size = fsl_ddr_sdram();
-
-	dram_size = setup_ddr_tlbs(dram_size / 0x100000);
-	dram_size *= 0x100000;
-
 #else
 	/* DDR has been initialised by first stage boot loader */
 	dram_size = fsl_ddr_sdram_size();
 #endif
+	dram_size = setup_ddr_tlbs(dram_size / 0x100000);
+	dram_size *= 0x100000;
+
 	return dram_size;
 }
diff --git a/board/freescale/t4qds/ddr.h b/board/freescale/t4qds/ddr.h
index 4d0e3c4..0b0cc9a 100644
--- a/board/freescale/t4qds/ddr.h
+++ b/board/freescale/t4qds/ddr.h
@@ -31,16 +31,16 @@
 	 *   num|  hi| rank|  clk| wrlvl |   wrlvl   |  wrlvl | cpo  |wrdata|2T
 	 * ranks| mhz| GB  |adjst| start |   ctl2    |  ctl3  |      |delay |
 	 */
-	{2,  1350, 4, 4,     8, 0x0809090b, 0x0c0c0d0a,   0xff,    2,  0},
-	{2,  1350, 0, 5,     7, 0x0709090b, 0x0c0c0d09,   0xff,    2,  0},
-	{2,  1666, 4, 4,     8, 0x080a0a0d, 0x0d10100b,   0xff,    2,  0},
-	{2,  1666, 0, 5,     7, 0x080a0a0c, 0x0d0d0e0a,   0xff,    2,  0},
-	{2,  1900, 0, 4,     8, 0x090a0b0e, 0x0f11120c,   0xff,    2,  0},
-	{2,  2140, 0, 4,     8, 0x090a0b0e, 0x0f11120c,   0xff,    2,  0},
-	{1,  1350, 0, 5,     8, 0x0809090b, 0x0c0c0d0a,   0xff,    2,  0},
-	{1,  1700, 0, 5,     8, 0x080a0a0c, 0x0c0d0e0a,   0xff,    2,  0},
-	{1,  1900, 0, 4,     8, 0x080a0a0c, 0x0e0e0f0a,   0xff,    2,  0},
-	{1,  2140, 0, 4,     8, 0x090a0b0c, 0x0e0f100b,   0xff,    2,  0},
+	{2,  1350, 4,  8,     8, 0x0809090b, 0x0c0c0d0a,   0xff,    2,  0},
+	{2,  1350, 0, 10,     7, 0x0709090b, 0x0c0c0d09,   0xff,    2,  0},
+	{2,  1666, 4,  8,     8, 0x080a0a0d, 0x0d10100b,   0xff,    2,  0},
+	{2,  1666, 0, 10,     7, 0x080a0a0c, 0x0d0d0e0a,   0xff,    2,  0},
+	{2,  1900, 0,  8,     8, 0x090a0b0e, 0x0f11120c,   0xff,    2,  0},
+	{2,  2140, 0,  8,     8, 0x090a0b0e, 0x0f11120c,   0xff,    2,  0},
+	{1,  1350, 0, 10,     8, 0x0809090b, 0x0c0c0d0a,   0xff,    2,  0},
+	{1,  1700, 0, 10,     8, 0x080a0a0c, 0x0c0d0e0a,   0xff,    2,  0},
+	{1,  1900, 0,  8,     8, 0x080a0a0c, 0x0e0e0f0a,   0xff,    2,  0},
+	{1,  2140, 0,  8,     8, 0x090a0b0c, 0x0e0f100b,   0xff,    2,  0},
 	{}
 };
 
@@ -50,15 +50,15 @@
 	 *   num|  hi| rank|  clk| wrlvl |   wrlvl   |  wrlvl | cpo  |wrdata|2T
 	 * ranks| mhz| GB  |adjst| start |   ctl2    |  ctl3  |      |delay |
 	 */
-	{4,  1350, 0, 5,     9, 0x08070605, 0x06070806,   0xff,    2,  0},
-	{4,  1666, 0, 5,    11, 0x0a080706, 0x07090906,   0xff,    2,  0},
-	{4,  2140, 0, 5,    12, 0x0b090807, 0x080a0b07,   0xff,    2,  0},
-	{2,  1350, 0, 5,     9, 0x08070605, 0x06070806,   0xff,    2,  0},
-	{2,  1666, 0, 5,    11, 0x0a090806, 0x08090a06,   0xff,    2,  0},
-	{2,  2140, 0, 5,    12, 0x0b090807, 0x080a0b07,   0xff,    2,  0},
-	{1,  1350, 0, 5,     9, 0x08070605, 0x06070806,   0xff,    2,  0},
-	{1,  1666, 0, 5,    11, 0x0a090806, 0x08090a06,   0xff,    2,  0},
-	{1,  2140, 0, 4,    12, 0x0b090807, 0x080a0b07,   0xff,    2,  0},
+	{4,  1350, 0, 10,     9, 0x08070605, 0x06070806,   0xff,    2,  0},
+	{4,  1666, 0, 10,    11, 0x0a080706, 0x07090906,   0xff,    2,  0},
+	{4,  2140, 0, 10,    12, 0x0b090807, 0x080a0b07,   0xff,    2,  0},
+	{2,  1350, 0, 10,     9, 0x08070605, 0x06070806,   0xff,    2,  0},
+	{2,  1666, 0, 10,    11, 0x0a090806, 0x08090a06,   0xff,    2,  0},
+	{2,  2140, 0, 10,    12, 0x0b090807, 0x080a0b07,   0xff,    2,  0},
+	{1,  1350, 0, 10,     9, 0x08070605, 0x06070806,   0xff,    2,  0},
+	{1,  1666, 0, 10,    11, 0x0a090806, 0x08090a06,   0xff,    2,  0},
+	{1,  2140, 0,  8,    12, 0x0b090807, 0x080a0b07,   0xff,    2,  0},
 	{}
 };
 
diff --git a/board/freescale/t4qds/spl.c b/board/freescale/t4qds/spl.c
index d52059a..6ca0f03 100644
--- a/board/freescale/t4qds/spl.c
+++ b/board/freescale/t4qds/spl.c
@@ -116,6 +116,7 @@
 	get_clocks();
 	mem_malloc_init(CONFIG_SPL_RELOC_MALLOC_ADDR,
 			CONFIG_SPL_RELOC_MALLOC_SIZE);
+	gd->flags |= GD_FLG_FULL_MALLOC_INIT;
 
 #ifdef CONFIG_SPL_NAND_BOOT
 	nand_spl_load_image(CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE,
diff --git a/board/freescale/t4rdb/Makefile b/board/freescale/t4rdb/Makefile
index 83b55ee..4f29eea 100644
--- a/board/freescale/t4rdb/Makefile
+++ b/board/freescale/t4rdb/Makefile
@@ -5,13 +5,14 @@
 #
 
 ifdef CONFIG_SPL_BUILD
-obj-y += spl.o
+obj-y	+= spl.o
 else
-obj-$(CONFIG_T4240RDB) += t4240rdb.o
-obj-y	+= cpld.o
-obj-y	+= eth.o
+obj-$(CONFIG_T4240RDB)	+= t4240rdb.o
+obj-y			+= cpld.o
+obj-y			+= eth.o
 obj-$(CONFIG_PCI)	+= pci.o
 endif
+
 obj-y	+= ddr.o
 obj-y	+= law.o
 obj-y	+= tlb.o
diff --git a/board/freescale/t4rdb/ddr.c b/board/freescale/t4rdb/ddr.c
index 27b37b5..230f031 100644
--- a/board/freescale/t4rdb/ddr.c
+++ b/board/freescale/t4rdb/ddr.c
@@ -110,13 +110,12 @@
 
 #if defined(CONFIG_SPL_BUILD) || !defined(CONFIG_RAMBOOT_PBL)
 	dram_size = fsl_ddr_sdram();
-
-	dram_size = setup_ddr_tlbs(dram_size / 0x100000);
-	dram_size *= 0x100000;
 #else
 	/* DDR has been initialised by first stage boot loader */
 	dram_size = fsl_ddr_sdram_size();
 #endif
+	dram_size = setup_ddr_tlbs(dram_size / 0x100000);
+	dram_size *= 0x100000;
 
 	return dram_size;
 }
diff --git a/board/freescale/t4rdb/ddr.h b/board/freescale/t4rdb/ddr.h
index 7b85476..f01ebb2 100644
--- a/board/freescale/t4rdb/ddr.h
+++ b/board/freescale/t4rdb/ddr.h
@@ -27,16 +27,16 @@
 	 *   num|  hi| rank|  clk| wrlvl |   wrlvl   |  wrlvl
 	 * ranks| mhz| GB  |adjst| start |   ctl2    |  ctl3
 	 */
-	{2,  1350, 4, 4,     8, 0x0809090b, 0x0c0c0d0a},
-	{2,  1350, 0, 5,     7, 0x0709090b, 0x0c0c0d09},
-	{2,  1666, 4, 4,     8, 0x080a0a0d, 0x0d10100b},
-	{2,  1666, 0, 5,     7, 0x080a0a0c, 0x0d0d0e0a},
-	{2,  1900, 0, 4,     8, 0x090a0b0e, 0x0f11120c},
-	{2,  2140, 0, 4,     8, 0x090a0b0e, 0x0f11120c},
-	{1,  1350, 0, 5,     8, 0x0809090b, 0x0c0c0d0a},
-	{1,  1700, 0, 5,     8, 0x080a0a0c, 0x0c0d0e0a},
-	{1,  1900, 0, 4,     8, 0x080a0a0c, 0x0e0e0f0a},
-	{1,  2140, 0, 4,     8, 0x090a0b0c, 0x0e0f100b},
+	{2,  1350, 4,  8,     8, 0x0809090b, 0x0c0c0d0a},
+	{2,  1350, 0, 10,     7, 0x0709090b, 0x0c0c0d09},
+	{2,  1666, 4,  8,     8, 0x080a0a0d, 0x0d10100b},
+	{2,  1666, 0, 10,     7, 0x080a0a0c, 0x0d0d0e0a},
+	{2,  1900, 0,  8,     8, 0x090a0b0e, 0x0f11120c},
+	{2,  2140, 0,  8,     8, 0x090a0b0e, 0x0f11120c},
+	{1,  1350, 0, 10,     8, 0x0809090b, 0x0c0c0d0a},
+	{1,  1700, 0, 10,     8, 0x080a0a0c, 0x0c0d0e0a},
+	{1,  1900, 0,  8,     8, 0x080a0a0c, 0x0e0e0f0a},
+	{1,  2140, 0,  8,     8, 0x090a0b0c, 0x0e0f100b},
 	{}
 };
 
@@ -46,15 +46,15 @@
 	 *   num|  hi| rank|  clk| wrlvl |   wrlvl   |  wrlvl
 	 * ranks| mhz| GB  |adjst| start |   ctl2    |  ctl3
 	 */
-	{4,  1350, 0, 5,     9, 0x08070605, 0x06070806},
-	{4,  1666, 0, 5,    11, 0x0a080706, 0x07090906},
-	{4,  2140, 0, 5,    12, 0x0b090807, 0x080a0b07},
-	{2,  1350, 0, 5,     9, 0x08070605, 0x06070806},
-	{2,  1666, 0, 5,    11, 0x0a090806, 0x08090a06},
-	{2,  2140, 0, 5,    12, 0x0b090807, 0x080a0b07},
-	{1,  1350, 0, 5,     9, 0x08070605, 0x06070806},
-	{1,  1666, 0, 5,    11, 0x0a090806, 0x08090a06},
-	{1,  2140, 0, 4,    12, 0x0b090807, 0x080a0b07},
+	{4,  1350, 0, 10,     9, 0x08070605, 0x06070806},
+	{4,  1666, 0, 10,    11, 0x0a080706, 0x07090906},
+	{4,  2140, 0, 10,    12, 0x0b090807, 0x080a0b07},
+	{2,  1350, 0, 10,     9, 0x08070605, 0x06070806},
+	{2,  1666, 0, 10,    11, 0x0a090806, 0x08090a06},
+	{2,  2140, 0, 10,    12, 0x0b090807, 0x080a0b07},
+	{1,  1350, 0, 10,     9, 0x08070605, 0x06070806},
+	{1,  1666, 0, 10,    11, 0x0a090806, 0x08090a06},
+	{1,  2140, 0,  8,    12, 0x0b090807, 0x080a0b07},
 	{}
 };
 
diff --git a/board/freescale/t4rdb/spl.c b/board/freescale/t4rdb/spl.c
index 4c1e0cc..b148a7f 100644
--- a/board/freescale/t4rdb/spl.c
+++ b/board/freescale/t4rdb/spl.c
@@ -80,6 +80,7 @@
 	get_clocks();
 	mem_malloc_init(CONFIG_SPL_RELOC_MALLOC_ADDR,
 			CONFIG_SPL_RELOC_MALLOC_SIZE);
+	gd->flags |= GD_FLG_FULL_MALLOC_INIT;
 
 	mmc_initialize(bd);
 	mmc_spl_load_image(CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE,
diff --git a/board/nvidia/cardhu/cardhu.c b/board/nvidia/cardhu/cardhu.c
index ba15e2e..f04f843 100644
--- a/board/nvidia/cardhu/cardhu.c
+++ b/board/nvidia/cardhu/cardhu.c
@@ -110,11 +110,11 @@
 	}
 
 	/* GPIO: PEX = 3.3V */
-	err = gpio_request(GPIO_PL7, "PEX");
+	err = gpio_request(TEGRA_GPIO(L, 7), "PEX");
 	if (err < 0)
 		return err;
 
-	gpio_direction_output(GPIO_PL7, 1);
+	gpio_direction_output(TEGRA_GPIO(L, 7), 1);
 
 	/* TPS659110: LDO2_REG = 1.05V, ACTIVE */
 	data[0] = 0x15;
diff --git a/board/nvidia/e2220-1170/pinmux-config-e2220-1170.h b/board/nvidia/e2220-1170/pinmux-config-e2220-1170.h
index 7eb1e6c..7955ca5 100644
--- a/board/nvidia/e2220-1170/pinmux-config-e2220-1170.h
+++ b/board/nvidia/e2220-1170/pinmux-config-e2220-1170.h
@@ -15,71 +15,71 @@
 #ifndef _PINMUX_CONFIG_E2220_1170_H_
 #define _PINMUX_CONFIG_E2220_1170_H_
 
-#define GPIO_INIT(_gpio, _init)				\
+#define GPIO_INIT(_port, _gpio, _init)			\
 	{						\
-		.gpio	= GPIO_P##_gpio,		\
+		.gpio	= TEGRA_GPIO(_port, _gpio),	\
 		.init	= TEGRA_GPIO_INIT_##_init,	\
 	}
 
 static const struct tegra_gpio_config e2220_1170_gpio_inits[] = {
-	/*        gpio, init_val */
-	GPIO_INIT(A5,   IN),
-	GPIO_INIT(A6,   IN),
-	GPIO_INIT(B4,   IN),
-	GPIO_INIT(E6,   IN),
-	GPIO_INIT(G2,   OUT0),
-	GPIO_INIT(G3,   OUT0),
-	GPIO_INIT(H0,   OUT0),
-	GPIO_INIT(H1,   OUT0),
-	GPIO_INIT(H2,   IN),
-	GPIO_INIT(H3,   OUT0),
-	GPIO_INIT(H4,   OUT0),
-	GPIO_INIT(H5,   IN),
-	GPIO_INIT(H6,   OUT0),
-	GPIO_INIT(H7,   OUT0),
-	GPIO_INIT(I0,   OUT0),
-	GPIO_INIT(I1,   IN),
-	GPIO_INIT(I2,   OUT0),
-	GPIO_INIT(I3,   OUT0),
-	GPIO_INIT(K0,   IN),
-	GPIO_INIT(K1,   OUT0),
-	GPIO_INIT(K2,   OUT0),
-	GPIO_INIT(K3,   OUT0),
-	GPIO_INIT(K4,   IN),
-	GPIO_INIT(K5,   OUT0),
-	GPIO_INIT(K6,   IN),
-	GPIO_INIT(K7,   OUT0),
-	GPIO_INIT(L0,   OUT0),
-	GPIO_INIT(S4,   OUT0),
-	GPIO_INIT(S5,   OUT0),
-	GPIO_INIT(S6,   OUT0),
-	GPIO_INIT(S7,   OUT0),
-	GPIO_INIT(T0,   OUT0),
-	GPIO_INIT(T1,   OUT0),
-	GPIO_INIT(V1,   OUT0),
-	GPIO_INIT(V2,   OUT0),
-	GPIO_INIT(V3,   IN),
-	GPIO_INIT(V5,   OUT0),
-	GPIO_INIT(V6,   OUT0),
-	GPIO_INIT(X0,   IN),
-	GPIO_INIT(X1,   IN),
-	GPIO_INIT(X2,   IN),
-	GPIO_INIT(X3,   IN),
-	GPIO_INIT(X4,   IN),
-	GPIO_INIT(X5,   IN),
-	GPIO_INIT(X6,   IN),
-	GPIO_INIT(X7,   IN),
-	GPIO_INIT(Y0,   IN),
-	GPIO_INIT(Y1,   IN),
-	GPIO_INIT(Z0,   IN),
-	GPIO_INIT(Z4,   OUT0),
-	GPIO_INIT(BB2,  OUT0),
-	GPIO_INIT(BB3,  OUT0),
-	GPIO_INIT(BB4,  IN),
-	GPIO_INIT(CC1,  IN),
-	GPIO_INIT(CC5,  OUT0),
-	GPIO_INIT(CC6,  IN),
-	GPIO_INIT(CC7,  OUT0),
+	/*        port, pin, init_val */
+	GPIO_INIT(A,    5,   IN),
+	GPIO_INIT(A,    6,   IN),
+	GPIO_INIT(B,    4,   IN),
+	GPIO_INIT(E,    6,   IN),
+	GPIO_INIT(G,    2,   OUT0),
+	GPIO_INIT(G,    3,   OUT0),
+	GPIO_INIT(H,    0,   OUT0),
+	GPIO_INIT(H,    1,   OUT0),
+	GPIO_INIT(H,    2,   IN),
+	GPIO_INIT(H,    3,   OUT0),
+	GPIO_INIT(H,    4,   OUT0),
+	GPIO_INIT(H,    5,   IN),
+	GPIO_INIT(H,    6,   OUT0),
+	GPIO_INIT(H,    7,   OUT0),
+	GPIO_INIT(I,    0,   OUT0),
+	GPIO_INIT(I,    1,   IN),
+	GPIO_INIT(I,    2,   OUT0),
+	GPIO_INIT(I,    3,   OUT0),
+	GPIO_INIT(K,    0,   IN),
+	GPIO_INIT(K,    1,   OUT0),
+	GPIO_INIT(K,    2,   OUT0),
+	GPIO_INIT(K,    3,   OUT0),
+	GPIO_INIT(K,    4,   IN),
+	GPIO_INIT(K,    5,   OUT0),
+	GPIO_INIT(K,    6,   IN),
+	GPIO_INIT(K,    7,   OUT0),
+	GPIO_INIT(L,    0,   OUT0),
+	GPIO_INIT(S,    4,   OUT0),
+	GPIO_INIT(S,    5,   OUT0),
+	GPIO_INIT(S,    6,   OUT0),
+	GPIO_INIT(S,    7,   OUT0),
+	GPIO_INIT(T,    0,   OUT0),
+	GPIO_INIT(T,    1,   OUT0),
+	GPIO_INIT(V,    1,   OUT0),
+	GPIO_INIT(V,    2,   OUT0),
+	GPIO_INIT(V,    3,   IN),
+	GPIO_INIT(V,    5,   OUT0),
+	GPIO_INIT(V,    6,   OUT0),
+	GPIO_INIT(X,    0,   IN),
+	GPIO_INIT(X,    1,   IN),
+	GPIO_INIT(X,    2,   IN),
+	GPIO_INIT(X,    3,   IN),
+	GPIO_INIT(X,    4,   IN),
+	GPIO_INIT(X,    5,   IN),
+	GPIO_INIT(X,    6,   IN),
+	GPIO_INIT(X,    7,   IN),
+	GPIO_INIT(Y,    0,   IN),
+	GPIO_INIT(Y,    1,   IN),
+	GPIO_INIT(Z,    0,   IN),
+	GPIO_INIT(Z,    4,   OUT0),
+	GPIO_INIT(BB,   2,   OUT0),
+	GPIO_INIT(BB,   3,   OUT0),
+	GPIO_INIT(BB,   4,   IN),
+	GPIO_INIT(CC,   1,   IN),
+	GPIO_INIT(CC,   5,   OUT0),
+	GPIO_INIT(CC,   6,   IN),
+	GPIO_INIT(CC,   7,   OUT0),
 };
 
 #define PINCFG(_pingrp, _mux, _pull, _tri, _io, _od, _e_io_hv)	\
diff --git a/board/nvidia/jetson-tk1/pinmux-config-jetson-tk1.h b/board/nvidia/jetson-tk1/pinmux-config-jetson-tk1.h
index 00e0cdc..01237db 100644
--- a/board/nvidia/jetson-tk1/pinmux-config-jetson-tk1.h
+++ b/board/nvidia/jetson-tk1/pinmux-config-jetson-tk1.h
@@ -15,63 +15,63 @@
 #ifndef _PINMUX_CONFIG_JETSON_TK1_H_
 #define _PINMUX_CONFIG_JETSON_TK1_H_
 
-#define GPIO_INIT(_gpio, _init)				\
+#define GPIO_INIT(_port, _gpio, _init)			\
 	{						\
-		.gpio	= GPIO_P##_gpio,		\
+		.gpio	= TEGRA_GPIO(_port, _gpio),	\
 		.init	= TEGRA_GPIO_INIT_##_init,	\
 	}
 
 static const struct tegra_gpio_config jetson_tk1_gpio_inits[] = {
-	/*        gpio, init_val */
-	GPIO_INIT(G0,   IN),
-	GPIO_INIT(G1,   IN),
-	GPIO_INIT(G2,   IN),
-	GPIO_INIT(G3,   IN),
-	GPIO_INIT(G4,   IN),
-	GPIO_INIT(H2,   OUT0),
-	GPIO_INIT(H4,   IN),
-	GPIO_INIT(H7,   IN),
-	GPIO_INIT(I0,   OUT0),
-	GPIO_INIT(I1,   IN),
-	GPIO_INIT(I6,   IN),
-	GPIO_INIT(J0,   IN),
-	GPIO_INIT(K1,   OUT0),
-	GPIO_INIT(K2,   IN),
-	GPIO_INIT(K4,   OUT0),
-	GPIO_INIT(K6,   OUT0),
-	GPIO_INIT(N7,   IN),
-	GPIO_INIT(O1,   IN),
-	GPIO_INIT(O4,   IN),
-	GPIO_INIT(P2,   OUT0),
-	GPIO_INIT(Q0,   IN),
-	GPIO_INIT(Q3,   IN),
-	GPIO_INIT(Q5,   IN),
-	GPIO_INIT(R0,   OUT0),
-	GPIO_INIT(R2,   OUT0),
-	GPIO_INIT(R4,   IN),
-	GPIO_INIT(R7,   IN),
-	GPIO_INIT(S7,   IN),
-	GPIO_INIT(T0,   OUT0),
-	GPIO_INIT(T1,   IN),
-	GPIO_INIT(U0,   IN),
-	GPIO_INIT(U1,   IN),
-	GPIO_INIT(U2,   IN),
-	GPIO_INIT(U3,   IN),
-	GPIO_INIT(U4,   IN),
-	GPIO_INIT(U5,   IN),
-	GPIO_INIT(U6,   IN),
-	GPIO_INIT(V0,   IN),
-	GPIO_INIT(V1,   IN),
-	GPIO_INIT(X1,   IN),
-	GPIO_INIT(X4,   IN),
-	GPIO_INIT(X7,   OUT0),
-	GPIO_INIT(BB3,  OUT0),
-	GPIO_INIT(BB5,  OUT0),
-	GPIO_INIT(BB6,  OUT0),
-	GPIO_INIT(BB7,  OUT0),
-	GPIO_INIT(CC1,  IN),
-	GPIO_INIT(CC2,  IN),
-	GPIO_INIT(EE2,  OUT1),
+	/*        port, pin, init_val */
+	GPIO_INIT(G,    0,   IN),
+	GPIO_INIT(G,    1,   IN),
+	GPIO_INIT(G,    2,   IN),
+	GPIO_INIT(G,    3,   IN),
+	GPIO_INIT(G,    4,   IN),
+	GPIO_INIT(H,    2,   OUT0),
+	GPIO_INIT(H,    4,   IN),
+	GPIO_INIT(H,    7,   IN),
+	GPIO_INIT(I,    0,   OUT0),
+	GPIO_INIT(I,    1,   IN),
+	GPIO_INIT(I,    6,   IN),
+	GPIO_INIT(J,    0,   IN),
+	GPIO_INIT(K,    1,   OUT0),
+	GPIO_INIT(K,    2,   IN),
+	GPIO_INIT(K,    4,   OUT0),
+	GPIO_INIT(K,    6,   OUT0),
+	GPIO_INIT(N,    7,   IN),
+	GPIO_INIT(O,    1,   IN),
+	GPIO_INIT(O,    4,   IN),
+	GPIO_INIT(P,    2,   OUT0),
+	GPIO_INIT(Q,    0,   IN),
+	GPIO_INIT(Q,    3,   IN),
+	GPIO_INIT(Q,    5,   IN),
+	GPIO_INIT(R,    0,   OUT0),
+	GPIO_INIT(R,    2,   OUT0),
+	GPIO_INIT(R,    4,   IN),
+	GPIO_INIT(R,    7,   IN),
+	GPIO_INIT(S,    7,   IN),
+	GPIO_INIT(T,    0,   OUT0),
+	GPIO_INIT(T,    1,   IN),
+	GPIO_INIT(U,    0,   IN),
+	GPIO_INIT(U,    1,   IN),
+	GPIO_INIT(U,    2,   IN),
+	GPIO_INIT(U,    3,   IN),
+	GPIO_INIT(U,    4,   IN),
+	GPIO_INIT(U,    5,   IN),
+	GPIO_INIT(U,    6,   IN),
+	GPIO_INIT(V,    0,   IN),
+	GPIO_INIT(V,    1,   IN),
+	GPIO_INIT(X,    1,   IN),
+	GPIO_INIT(X,    4,   IN),
+	GPIO_INIT(X,    7,   OUT0),
+	GPIO_INIT(BB,   3,   OUT0),
+	GPIO_INIT(BB,   5,   OUT0),
+	GPIO_INIT(BB,   6,   OUT0),
+	GPIO_INIT(BB,   7,   OUT0),
+	GPIO_INIT(CC,   1,   IN),
+	GPIO_INIT(CC,   2,   IN),
+	GPIO_INIT(EE,   2,   OUT1),
 };
 
 #define PINCFG(_pingrp, _mux, _pull, _tri, _io, _od, _rcv_sel)	\
diff --git a/board/nvidia/nyan-big/nyan-big.c b/board/nvidia/nyan-big/nyan-big.c
index ba96401..8f68ae9 100644
--- a/board/nvidia/nyan-big/nyan-big.c
+++ b/board/nvidia/nyan-big/nyan-big.c
@@ -36,8 +36,9 @@
 
 int tegra_board_id(void)
 {
-	static const int vector[] = {GPIO_PQ3, GPIO_PT1, GPIO_PX1,
-					GPIO_PX4, -1};
+	static const int vector[] = {TEGRA_GPIO(Q, 3), TEGRA_GPIO(T, 1),
+					TEGRA_GPIO(X, 1), TEGRA_GPIO(X, 4),
+					-1};
 
 	gpio_claim_vector(vector, "board_id%d");
 	return gpio_get_values_as_int(vector);
diff --git a/board/nvidia/nyan-big/pinmux-config-nyan-big.h b/board/nvidia/nyan-big/pinmux-config-nyan-big.h
index dca0171..fd7f1d1 100644
--- a/board/nvidia/nyan-big/pinmux-config-nyan-big.h
+++ b/board/nvidia/nyan-big/pinmux-config-nyan-big.h
@@ -15,59 +15,59 @@
 #ifndef _PINMUX_CONFIG_NYAN_BIG_H_
 #define _PINMUX_CONFIG_NYAN_BIG_H_
 
-#define GPIO_INIT(_gpio, _init)				\
+#define GPIO_INIT(_port, _gpio, _init)			\
 	{						\
-		.gpio	= GPIO_P##_gpio,		\
+		.gpio	= TEGRA_GPIO(_port, _gpio),	\
 		.init	= TEGRA_GPIO_INIT_##_init,	\
 	}
 
 static const struct tegra_gpio_config nyan_big_gpio_inits[] = {
-	/*        gpio, init_val */
-	GPIO_INIT(A0,   IN),
-	GPIO_INIT(C7,   IN),
-	GPIO_INIT(G0,   IN),
-	GPIO_INIT(G1,   IN),
-	GPIO_INIT(G2,   IN),
-	GPIO_INIT(G3,   IN),
-	GPIO_INIT(H2,   IN),
-	GPIO_INIT(H4,   IN),
-	GPIO_INIT(H6,   IN),
-	GPIO_INIT(H7,   OUT1),
-	GPIO_INIT(I0,   IN),
-	GPIO_INIT(I1,   IN),
-	GPIO_INIT(I5,   OUT1),
-	GPIO_INIT(I6,   IN),
-	GPIO_INIT(I7,   IN),
-	GPIO_INIT(J0,   IN),
-	GPIO_INIT(J7,   IN),
-	GPIO_INIT(K1,   OUT0),
-	GPIO_INIT(K2,   IN),
-	GPIO_INIT(K4,   OUT0),
-	GPIO_INIT(K6,   OUT0),
-	GPIO_INIT(K7,   IN),
-	GPIO_INIT(N7,   IN),
-	GPIO_INIT(P2,   OUT0),
-	GPIO_INIT(Q0,   IN),
-	GPIO_INIT(Q2,   IN),
-	GPIO_INIT(Q3,   IN),
-	GPIO_INIT(Q6,   IN),
-	GPIO_INIT(Q7,   IN),
-	GPIO_INIT(R0,   OUT0),
-	GPIO_INIT(R1,   IN),
-	GPIO_INIT(R4,   IN),
-	GPIO_INIT(R7,   IN),
-	GPIO_INIT(S3,   OUT0),
-	GPIO_INIT(S4,   OUT0),
-	GPIO_INIT(S7,   IN),
-	GPIO_INIT(T1,   IN),
-	GPIO_INIT(U4,   IN),
-	GPIO_INIT(U5,   IN),
-	GPIO_INIT(U6,   IN),
-	GPIO_INIT(V0,   IN),
-	GPIO_INIT(W3,   IN),
-	GPIO_INIT(X1,   IN),
-	GPIO_INIT(X4,   IN),
-	GPIO_INIT(X7,   OUT0),
+	/*        port, pin, init_val */
+	GPIO_INIT(A,    0,   IN),
+	GPIO_INIT(C,    7,   IN),
+	GPIO_INIT(G,    0,   IN),
+	GPIO_INIT(G,    1,   IN),
+	GPIO_INIT(G,    2,   IN),
+	GPIO_INIT(G,    3,   IN),
+	GPIO_INIT(H,    2,   IN),
+	GPIO_INIT(H,    4,   IN),
+	GPIO_INIT(H,    6,   IN),
+	GPIO_INIT(H,    7,   OUT1),
+	GPIO_INIT(I,    0,   IN),
+	GPIO_INIT(I,    1,   IN),
+	GPIO_INIT(I,    5,   OUT1),
+	GPIO_INIT(I,    6,   IN),
+	GPIO_INIT(I,    7,   IN),
+	GPIO_INIT(J,    0,   IN),
+	GPIO_INIT(J,    7,   IN),
+	GPIO_INIT(K,    1,   OUT0),
+	GPIO_INIT(K,    2,   IN),
+	GPIO_INIT(K,    4,   OUT0),
+	GPIO_INIT(K,    6,   OUT0),
+	GPIO_INIT(K,    7,   IN),
+	GPIO_INIT(N,    7,   IN),
+	GPIO_INIT(P,    2,   OUT0),
+	GPIO_INIT(Q,    0,   IN),
+	GPIO_INIT(Q,    2,   IN),
+	GPIO_INIT(Q,    3,   IN),
+	GPIO_INIT(Q,    6,   IN),
+	GPIO_INIT(Q,    7,   IN),
+	GPIO_INIT(R,    0,   OUT0),
+	GPIO_INIT(R,    1,   IN),
+	GPIO_INIT(R,    4,   IN),
+	GPIO_INIT(R,    7,   IN),
+	GPIO_INIT(S,    3,   OUT0),
+	GPIO_INIT(S,    4,   OUT0),
+	GPIO_INIT(S,    7,   IN),
+	GPIO_INIT(T,    1,   IN),
+	GPIO_INIT(U,    4,   IN),
+	GPIO_INIT(U,    5,   IN),
+	GPIO_INIT(U,    6,   IN),
+	GPIO_INIT(V,    0,   IN),
+	GPIO_INIT(W,    3,   IN),
+	GPIO_INIT(X,    1,   IN),
+	GPIO_INIT(X,    4,   IN),
+	GPIO_INIT(X,    7,   OUT0),
 };
 
 #define PINCFG(_pingrp, _mux, _pull, _tri, _io, _od, _rcv_sel)	\
diff --git a/board/nvidia/p2371-0000/pinmux-config-p2371-0000.h b/board/nvidia/p2371-0000/pinmux-config-p2371-0000.h
index 35706b4..24acbcc 100644
--- a/board/nvidia/p2371-0000/pinmux-config-p2371-0000.h
+++ b/board/nvidia/p2371-0000/pinmux-config-p2371-0000.h
@@ -15,62 +15,62 @@
 #ifndef _PINMUX_CONFIG_P2371_0000_H_
 #define _PINMUX_CONFIG_P2371_0000_H_
 
-#define GPIO_INIT(_gpio, _init)				\
+#define GPIO_INIT(_port, _gpio, _init)			\
 	{						\
-		.gpio	= GPIO_P##_gpio,		\
+		.gpio	= TEGRA_GPIO(_port, _gpio),	\
 		.init	= TEGRA_GPIO_INIT_##_init,	\
 	}
 
 static const struct tegra_gpio_config p2371_0000_gpio_inits[] = {
-	/*        gpio, init_val */
-	GPIO_INIT(A5,   IN),
-	GPIO_INIT(E4,   OUT0),
-	GPIO_INIT(E6,   IN),
-	GPIO_INIT(G0,   IN),
-	GPIO_INIT(G3,   OUT0),
-	GPIO_INIT(H0,   OUT0),
-	GPIO_INIT(H2,   IN),
-	GPIO_INIT(H3,   OUT0),
-	GPIO_INIT(H4,   OUT0),
-	GPIO_INIT(H5,   IN),
-	GPIO_INIT(H6,   OUT0),
-	GPIO_INIT(H7,   OUT0),
-	GPIO_INIT(I0,   OUT0),
-	GPIO_INIT(I1,   IN),
-	GPIO_INIT(I2,   OUT0),
-	GPIO_INIT(I3,   OUT0),
-	GPIO_INIT(K4,   IN),
-	GPIO_INIT(K5,   OUT0),
-	GPIO_INIT(K6,   IN),
-	GPIO_INIT(K7,   OUT0),
-	GPIO_INIT(L0,   OUT0),
-	GPIO_INIT(S4,   OUT0),
-	GPIO_INIT(S5,   OUT0),
-	GPIO_INIT(S6,   OUT0),
-	GPIO_INIT(S7,   OUT0),
-	GPIO_INIT(T0,   OUT0),
-	GPIO_INIT(T1,   OUT0),
-	GPIO_INIT(V1,   OUT0),
-	GPIO_INIT(V2,   OUT0),
-	GPIO_INIT(V5,   OUT0),
-	GPIO_INIT(V6,   OUT0),
-	GPIO_INIT(V7,   OUT1),
-	GPIO_INIT(X0,   IN),
-	GPIO_INIT(X1,   IN),
-	GPIO_INIT(X2,   IN),
-	GPIO_INIT(X3,   IN),
-	GPIO_INIT(X4,   IN),
-	GPIO_INIT(X5,   IN),
-	GPIO_INIT(X6,   IN),
-	GPIO_INIT(X7,   IN),
-	GPIO_INIT(Y1,   IN),
-	GPIO_INIT(Z0,   IN),
-	GPIO_INIT(Z4,   OUT0),
-	GPIO_INIT(BB2,  OUT0),
-	GPIO_INIT(BB3,  OUT0),
-	GPIO_INIT(CC1,  IN),
-	GPIO_INIT(CC6,  IN),
-	GPIO_INIT(CC7,  OUT0),
+	/*        port, pin, init_val */
+	GPIO_INIT(A,    5,   IN),
+	GPIO_INIT(E,    4,   OUT0),
+	GPIO_INIT(E,    6,   IN),
+	GPIO_INIT(G,    0,   IN),
+	GPIO_INIT(G,    3,   OUT0),
+	GPIO_INIT(H,    0,   OUT0),
+	GPIO_INIT(H,    2,   IN),
+	GPIO_INIT(H,    3,   OUT0),
+	GPIO_INIT(H,    4,   OUT0),
+	GPIO_INIT(H,    5,   IN),
+	GPIO_INIT(H,    6,   OUT0),
+	GPIO_INIT(H,    7,   OUT0),
+	GPIO_INIT(I,    0,   OUT0),
+	GPIO_INIT(I,    1,   IN),
+	GPIO_INIT(I,    2,   OUT0),
+	GPIO_INIT(I,    3,   OUT0),
+	GPIO_INIT(K,    4,   IN),
+	GPIO_INIT(K,    5,   OUT0),
+	GPIO_INIT(K,    6,   IN),
+	GPIO_INIT(K,    7,   OUT0),
+	GPIO_INIT(L,    0,   OUT0),
+	GPIO_INIT(S,    4,   OUT0),
+	GPIO_INIT(S,    5,   OUT0),
+	GPIO_INIT(S,    6,   OUT0),
+	GPIO_INIT(S,    7,   OUT0),
+	GPIO_INIT(T,    0,   OUT0),
+	GPIO_INIT(T,    1,   OUT0),
+	GPIO_INIT(V,    1,   OUT0),
+	GPIO_INIT(V,    2,   OUT0),
+	GPIO_INIT(V,    5,   OUT0),
+	GPIO_INIT(V,    6,   OUT0),
+	GPIO_INIT(V,    7,   OUT1),
+	GPIO_INIT(X,    0,   IN),
+	GPIO_INIT(X,    1,   IN),
+	GPIO_INIT(X,    2,   IN),
+	GPIO_INIT(X,    3,   IN),
+	GPIO_INIT(X,    4,   IN),
+	GPIO_INIT(X,    5,   IN),
+	GPIO_INIT(X,    6,   IN),
+	GPIO_INIT(X,    7,   IN),
+	GPIO_INIT(Y,    1,   IN),
+	GPIO_INIT(Z,    0,   IN),
+	GPIO_INIT(Z,    4,   OUT0),
+	GPIO_INIT(BB,   2,   OUT0),
+	GPIO_INIT(BB,   3,   OUT0),
+	GPIO_INIT(CC,   1,   IN),
+	GPIO_INIT(CC,   6,   IN),
+	GPIO_INIT(CC,   7,   OUT0),
 };
 
 #define PINCFG(_pingrp, _mux, _pull, _tri, _io, _od, _e_io_hv)	\
diff --git a/board/nvidia/p2371-2180/pinmux-config-p2371-2180.h b/board/nvidia/p2371-2180/pinmux-config-p2371-2180.h
index d5be6ec..601728e 100644
--- a/board/nvidia/p2371-2180/pinmux-config-p2371-2180.h
+++ b/board/nvidia/p2371-2180/pinmux-config-p2371-2180.h
@@ -15,73 +15,73 @@
 #ifndef _PINMUX_CONFIG_P2371_2180_H_
 #define _PINMUX_CONFIG_P2371_2180_H_
 
-#define GPIO_INIT(_gpio, _init)				\
+#define GPIO_INIT(_port, _gpio, _init)			\
 	{						\
-		.gpio	= GPIO_P##_gpio,		\
+		.gpio	= TEGRA_GPIO(_port, _gpio),	\
 		.init	= TEGRA_GPIO_INIT_##_init,	\
 	}
 
 static const struct tegra_gpio_config p2371_2180_gpio_inits[] = {
-	/*        gpio, init_val */
-	GPIO_INIT(A5,   IN),
-	GPIO_INIT(B0,   IN),
-	GPIO_INIT(B1,   IN),
-	GPIO_INIT(B2,   IN),
-	GPIO_INIT(B3,   IN),
-	GPIO_INIT(C0,   IN),
-	GPIO_INIT(C1,   IN),
-	GPIO_INIT(C2,   IN),
-	GPIO_INIT(C3,   IN),
-	GPIO_INIT(C4,   IN),
-	GPIO_INIT(E4,   IN),
-	GPIO_INIT(E5,   IN),
-	GPIO_INIT(E6,   IN),
-	GPIO_INIT(H0,   OUT0),
-	GPIO_INIT(H1,   OUT0),
-	GPIO_INIT(H2,   IN),
-	GPIO_INIT(H3,   OUT0),
-	GPIO_INIT(H4,   OUT0),
-	GPIO_INIT(H5,   IN),
-	GPIO_INIT(H6,   IN),
-	GPIO_INIT(H7,   IN),
-	GPIO_INIT(I0,   OUT0),
-	GPIO_INIT(I1,   IN),
-	GPIO_INIT(I2,   OUT0),
-	GPIO_INIT(K4,   IN),
-	GPIO_INIT(K5,   OUT0),
-	GPIO_INIT(K6,   IN),
-	GPIO_INIT(K7,   IN),
-	GPIO_INIT(L1,   IN),
-	GPIO_INIT(S4,   OUT0),
-	GPIO_INIT(S5,   OUT0),
-	GPIO_INIT(S6,   OUT0),
-	GPIO_INIT(S7,   OUT0),
-	GPIO_INIT(T0,   OUT0),
-	GPIO_INIT(T1,   OUT0),
-	GPIO_INIT(U2,   IN),
-	GPIO_INIT(U3,   IN),
-	GPIO_INIT(V1,   OUT0),
-	GPIO_INIT(V2,   OUT0),
-	GPIO_INIT(V3,   IN),
-	GPIO_INIT(V5,   OUT0),
-	GPIO_INIT(V6,   OUT0),
-	GPIO_INIT(X0,   IN),
-	GPIO_INIT(X1,   IN),
-	GPIO_INIT(X2,   IN),
-	GPIO_INIT(X3,   IN),
-	GPIO_INIT(X4,   IN),
-	GPIO_INIT(X5,   IN),
-	GPIO_INIT(X6,   IN),
-	GPIO_INIT(X7,   IN),
-	GPIO_INIT(Y0,   IN),
-	GPIO_INIT(Y1,   IN),
-	GPIO_INIT(Z0,   IN),
-	GPIO_INIT(Z2,   IN),
-	GPIO_INIT(Z3,   OUT0),
-	GPIO_INIT(BB0,  IN),
-	GPIO_INIT(BB2,  OUT0),
-	GPIO_INIT(BB3,  IN),
-	GPIO_INIT(CC1,  IN),
+	/*        port, pin, init_val */
+	GPIO_INIT(A,    5,   IN),
+	GPIO_INIT(B,    0,   IN),
+	GPIO_INIT(B,    1,   IN),
+	GPIO_INIT(B,    2,   IN),
+	GPIO_INIT(B,    3,   IN),
+	GPIO_INIT(C,    0,   IN),
+	GPIO_INIT(C,    1,   IN),
+	GPIO_INIT(C,    2,   IN),
+	GPIO_INIT(C,    3,   IN),
+	GPIO_INIT(C,    4,   IN),
+	GPIO_INIT(E,    4,   IN),
+	GPIO_INIT(E,    5,   IN),
+	GPIO_INIT(E,    6,   IN),
+	GPIO_INIT(H,    0,   OUT0),
+	GPIO_INIT(H,    1,   OUT0),
+	GPIO_INIT(H,    2,   IN),
+	GPIO_INIT(H,    3,   OUT0),
+	GPIO_INIT(H,    4,   OUT0),
+	GPIO_INIT(H,    5,   IN),
+	GPIO_INIT(H,    6,   IN),
+	GPIO_INIT(H,    7,   IN),
+	GPIO_INIT(I,    0,   OUT0),
+	GPIO_INIT(I,    1,   IN),
+	GPIO_INIT(I,    2,   OUT0),
+	GPIO_INIT(K,    4,   IN),
+	GPIO_INIT(K,    5,   OUT0),
+	GPIO_INIT(K,    6,   IN),
+	GPIO_INIT(K,    7,   IN),
+	GPIO_INIT(L,    1,   IN),
+	GPIO_INIT(S,    4,   OUT0),
+	GPIO_INIT(S,    5,   OUT0),
+	GPIO_INIT(S,    6,   OUT0),
+	GPIO_INIT(S,    7,   OUT0),
+	GPIO_INIT(T,    0,   OUT0),
+	GPIO_INIT(T,    1,   OUT0),
+	GPIO_INIT(U,    2,   IN),
+	GPIO_INIT(U,    3,   IN),
+	GPIO_INIT(V,    1,   OUT0),
+	GPIO_INIT(V,    2,   OUT0),
+	GPIO_INIT(V,    3,   IN),
+	GPIO_INIT(V,    5,   OUT0),
+	GPIO_INIT(V,    6,   OUT0),
+	GPIO_INIT(X,    0,   IN),
+	GPIO_INIT(X,    1,   IN),
+	GPIO_INIT(X,    2,   IN),
+	GPIO_INIT(X,    3,   IN),
+	GPIO_INIT(X,    4,   IN),
+	GPIO_INIT(X,    5,   IN),
+	GPIO_INIT(X,    6,   IN),
+	GPIO_INIT(X,    7,   IN),
+	GPIO_INIT(Y,    0,   IN),
+	GPIO_INIT(Y,    1,   IN),
+	GPIO_INIT(Z,    0,   IN),
+	GPIO_INIT(Z,    2,   IN),
+	GPIO_INIT(Z,    3,   OUT0),
+	GPIO_INIT(BB,   0,   IN),
+	GPIO_INIT(BB,   2,   OUT0),
+	GPIO_INIT(BB,   3,   IN),
+	GPIO_INIT(CC,   1,   IN),
 };
 
 #define PINCFG(_pingrp, _mux, _pull, _tri, _io, _od, _e_io_hv)	\
diff --git a/board/nvidia/p2571/p2571.c b/board/nvidia/p2571/p2571.c
index d80a7d0..7ce656f 100644
--- a/board/nvidia/p2571/p2571.c
+++ b/board/nvidia/p2571/p2571.c
@@ -58,6 +58,6 @@
 void start_cpu_fan(void)
 {
 	/* GPIO_PE4 is PS_VDD_FAN_ENABLE */
-	gpio_request(GPIO_PE4, "FAN_VDD");
-	gpio_direction_output(GPIO_PE4, 1);
+	gpio_request(TEGRA_GPIO(E, 4), "FAN_VDD");
+	gpio_direction_output(TEGRA_GPIO(E, 4), 1);
 }
diff --git a/board/nvidia/p2571/pinmux-config-p2571.h b/board/nvidia/p2571/pinmux-config-p2571.h
index d323301..dd4228f 100644
--- a/board/nvidia/p2571/pinmux-config-p2571.h
+++ b/board/nvidia/p2571/pinmux-config-p2571.h
@@ -15,37 +15,37 @@
 #ifndef _PINMUX_CONFIG_P2571_H_
 #define _PINMUX_CONFIG_P2571_H_
 
-#define GPIO_INIT(_gpio, _init)				\
+#define GPIO_INIT(_port, _gpio, _init)			\
 	{						\
-		.gpio	= GPIO_P##_gpio,		\
+		.gpio	= TEGRA_GPIO(_port, _gpio),	\
 		.init	= TEGRA_GPIO_INIT_##_init,	\
 	}
 
 static const struct tegra_gpio_config p2571_gpio_inits[] = {
-	/*        gpio, init_val */
-	GPIO_INIT(A0,   IN),
-	GPIO_INIT(A5,   IN),
-	GPIO_INIT(D4,   IN),
-	GPIO_INIT(E4,   OUT0),
-	GPIO_INIT(G0,   IN),
-	GPIO_INIT(H0,   OUT0),
-	GPIO_INIT(H2,   IN),
-	GPIO_INIT(H3,   OUT0),
-	GPIO_INIT(H4,   OUT0),
-	GPIO_INIT(H5,   IN),
-	GPIO_INIT(I0,   OUT0),
-	GPIO_INIT(I1,   IN),
-	GPIO_INIT(V1,   OUT0),
-	GPIO_INIT(V6,   OUT1),
-	GPIO_INIT(X4,   IN),
-	GPIO_INIT(X6,   IN),
-	GPIO_INIT(X7,   IN),
-	GPIO_INIT(Y1,   IN),
-	GPIO_INIT(Z0,   IN),
-	GPIO_INIT(Z4,   OUT0),
-	GPIO_INIT(BB2,  OUT0),
-	GPIO_INIT(CC1,  IN),
-	GPIO_INIT(CC3,  IN),
+	/*        port, pin, init_val */
+	GPIO_INIT(A,    0,   IN),
+	GPIO_INIT(A,    5,   IN),
+	GPIO_INIT(D,    4,   IN),
+	GPIO_INIT(E,    4,   OUT0),
+	GPIO_INIT(G,    0,   IN),
+	GPIO_INIT(H,    0,   OUT0),
+	GPIO_INIT(H,    2,   IN),
+	GPIO_INIT(H,    3,   OUT0),
+	GPIO_INIT(H,    4,   OUT0),
+	GPIO_INIT(H,    5,   IN),
+	GPIO_INIT(I,    0,   OUT0),
+	GPIO_INIT(I,    1,   IN),
+	GPIO_INIT(V,    1,   OUT0),
+	GPIO_INIT(V,    6,   OUT1),
+	GPIO_INIT(X,    4,   IN),
+	GPIO_INIT(X,    6,   IN),
+	GPIO_INIT(X,    7,   IN),
+	GPIO_INIT(Y,    1,   IN),
+	GPIO_INIT(Z,    0,   IN),
+	GPIO_INIT(Z,    4,   OUT0),
+	GPIO_INIT(BB,   2,   OUT0),
+	GPIO_INIT(CC,   1,   IN),
+	GPIO_INIT(CC,   3,   IN),
 };
 
 #define PINCFG(_pingrp, _mux, _pull, _tri, _io, _od, _e_io_hv)	\
diff --git a/board/nvidia/p2771-0000/Kconfig b/board/nvidia/p2771-0000/Kconfig
new file mode 100644
index 0000000..1b1116f
--- /dev/null
+++ b/board/nvidia/p2771-0000/Kconfig
@@ -0,0 +1,16 @@
+# Copyright (c) 2016, NVIDIA CORPORATION.
+#
+# SPDX-License-Identifier: GPL-2.0
+
+if TARGET_P2771_0000
+
+config SYS_BOARD
+	default "p2771-0000"
+
+config SYS_VENDOR
+	default "nvidia"
+
+config SYS_CONFIG_NAME
+	default "p2771-0000"
+
+endif
diff --git a/board/nvidia/p2771-0000/MAINTAINERS b/board/nvidia/p2771-0000/MAINTAINERS
new file mode 100644
index 0000000..4fc4ebd
--- /dev/null
+++ b/board/nvidia/p2771-0000/MAINTAINERS
@@ -0,0 +1,6 @@
+P2771-0000 BOARD
+M:	Stephen Warren <swarren@nvidia.com>
+S:	Maintained
+F:	board/nvidia/p2771-0000/
+F:	include/configs/p2771-0000.h
+F:	configs/p2771-0000_defconfig
diff --git a/board/nvidia/p2771-0000/Makefile b/board/nvidia/p2771-0000/Makefile
new file mode 100644
index 0000000..b28a47d
--- /dev/null
+++ b/board/nvidia/p2771-0000/Makefile
@@ -0,0 +1,5 @@
+# Copyright (c) 2016, NVIDIA CORPORATION.
+#
+# SPDX-License-Identifier: GPL-2.0
+
+obj-y	+= p2771-0000.o
diff --git a/board/nvidia/p2771-0000/p2771-0000.c b/board/nvidia/p2771-0000/p2771-0000.c
new file mode 100644
index 0000000..4ba8ebc
--- /dev/null
+++ b/board/nvidia/p2771-0000/p2771-0000.c
@@ -0,0 +1,7 @@
+/*
+ * Copyright (c) 2016, NVIDIA CORPORATION
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <common.h>
diff --git a/board/nvidia/seaboard/seaboard.c b/board/nvidia/seaboard/seaboard.c
index 2d07001..fc9c1c9 100644
--- a/board/nvidia/seaboard/seaboard.c
+++ b/board/nvidia/seaboard/seaboard.c
@@ -20,8 +20,8 @@
 void gpio_early_init_uart(void)
 {
 	/* Enable UART via GPIO_PI3 (port 8, bit 3) so serial console works */
-	gpio_request(GPIO_PI3, "uart_en");
-	gpio_direction_output(GPIO_PI3, 0);
+	gpio_request(TEGRA_GPIO(I, 3), "uart_en");
+	gpio_direction_output(TEGRA_GPIO(I, 3), 0);
 }
 #endif
 
diff --git a/board/nvidia/venice2/pinmux-config-venice2.h b/board/nvidia/venice2/pinmux-config-venice2.h
index fb444b3..59d53ef 100644
--- a/board/nvidia/venice2/pinmux-config-venice2.h
+++ b/board/nvidia/venice2/pinmux-config-venice2.h
@@ -15,70 +15,70 @@
 #ifndef _PINMUX_CONFIG_VENICE2_H_
 #define _PINMUX_CONFIG_VENICE2_H_
 
-#define GPIO_INIT(_gpio, _init)				\
+#define GPIO_INIT(_port, _gpio, _init)			\
 	{						\
-		.gpio	= GPIO_P##_gpio,		\
+		.gpio	= TEGRA_GPIO(_port, _gpio),	\
 		.init	= TEGRA_GPIO_INIT_##_init,	\
 	}
 
 static const struct tegra_gpio_config venice2_gpio_inits[] = {
-	/*        gpio, init_val */
-	GPIO_INIT(A0,   IN),
-	GPIO_INIT(C7,   IN),
-	GPIO_INIT(G0,   IN),
-	GPIO_INIT(G1,   IN),
-	GPIO_INIT(G2,   IN),
-	GPIO_INIT(G3,   IN),
-	GPIO_INIT(H2,   IN),
-	GPIO_INIT(H4,   IN),
-	GPIO_INIT(H5,   OUT0),
-	GPIO_INIT(H6,   IN),
-	GPIO_INIT(H7,   OUT1),
-	GPIO_INIT(I0,   IN),
-	GPIO_INIT(I1,   IN),
-	GPIO_INIT(I2,   OUT0),
-	GPIO_INIT(I4,   OUT0),
-	GPIO_INIT(I5,   OUT1),
-	GPIO_INIT(I6,   IN),
-	GPIO_INIT(J0,   IN),
-	GPIO_INIT(J7,   IN),
-	GPIO_INIT(K0,   IN),
-	GPIO_INIT(K1,   OUT0),
-	GPIO_INIT(K2,   IN),
-	GPIO_INIT(K3,   IN),
-	GPIO_INIT(K4,   OUT0),
-	GPIO_INIT(K6,   OUT0),
-	GPIO_INIT(K7,   IN),
-	GPIO_INIT(N7,   IN),
-	GPIO_INIT(O2,   IN),
-	GPIO_INIT(O5,   IN),
-	GPIO_INIT(O6,   OUT0),
-	GPIO_INIT(O7,   IN),
-	GPIO_INIT(P2,   OUT0),
-	GPIO_INIT(Q0,   IN),
-	GPIO_INIT(Q2,   IN),
-	GPIO_INIT(Q3,   IN),
-	GPIO_INIT(Q6,   IN),
-	GPIO_INIT(Q7,   IN),
-	GPIO_INIT(R0,   OUT0),
-	GPIO_INIT(R1,   IN),
-	GPIO_INIT(R4,   IN),
-	GPIO_INIT(S0,   IN),
-	GPIO_INIT(S3,   OUT0),
-	GPIO_INIT(S4,   OUT0),
-	GPIO_INIT(S7,   IN),
-	GPIO_INIT(T1,   IN),
-	GPIO_INIT(U4,   IN),
-	GPIO_INIT(U5,   IN),
-	GPIO_INIT(U6,   IN),
-	GPIO_INIT(V0,   IN),
-	GPIO_INIT(V1,   IN),
-	GPIO_INIT(W3,   IN),
-	GPIO_INIT(X1,   IN),
-	GPIO_INIT(X3,   IN),
-	GPIO_INIT(X4,   IN),
-	GPIO_INIT(X7,   OUT0),
-	GPIO_INIT(CC5,  OUT0),
+	/*        port, pin, init_val */
+	GPIO_INIT(A,    0,   IN),
+	GPIO_INIT(C,    7,   IN),
+	GPIO_INIT(G,    0,   IN),
+	GPIO_INIT(G,    1,   IN),
+	GPIO_INIT(G,    2,   IN),
+	GPIO_INIT(G,    3,   IN),
+	GPIO_INIT(H,    2,   IN),
+	GPIO_INIT(H,    4,   IN),
+	GPIO_INIT(H,    5,   OUT0),
+	GPIO_INIT(H,    6,   IN),
+	GPIO_INIT(H,    7,   OUT1),
+	GPIO_INIT(I,    0,   IN),
+	GPIO_INIT(I,    1,   IN),
+	GPIO_INIT(I,    2,   OUT0),
+	GPIO_INIT(I,    4,   OUT0),
+	GPIO_INIT(I,    5,   OUT1),
+	GPIO_INIT(I,    6,   IN),
+	GPIO_INIT(J,    0,   IN),
+	GPIO_INIT(J,    7,   IN),
+	GPIO_INIT(K,    0,   IN),
+	GPIO_INIT(K,    1,   OUT0),
+	GPIO_INIT(K,    2,   IN),
+	GPIO_INIT(K,    3,   IN),
+	GPIO_INIT(K,    4,   OUT0),
+	GPIO_INIT(K,    6,   OUT0),
+	GPIO_INIT(K,    7,   IN),
+	GPIO_INIT(N,    7,   IN),
+	GPIO_INIT(O,    2,   IN),
+	GPIO_INIT(O,    5,   IN),
+	GPIO_INIT(O,    6,   OUT0),
+	GPIO_INIT(O,    7,   IN),
+	GPIO_INIT(P,    2,   OUT0),
+	GPIO_INIT(Q,    0,   IN),
+	GPIO_INIT(Q,    2,   IN),
+	GPIO_INIT(Q,    3,   IN),
+	GPIO_INIT(Q,    6,   IN),
+	GPIO_INIT(Q,    7,   IN),
+	GPIO_INIT(R,    0,   OUT0),
+	GPIO_INIT(R,    1,   IN),
+	GPIO_INIT(R,    4,   IN),
+	GPIO_INIT(S,    0,   IN),
+	GPIO_INIT(S,    3,   OUT0),
+	GPIO_INIT(S,    4,   OUT0),
+	GPIO_INIT(S,    7,   IN),
+	GPIO_INIT(T,    1,   IN),
+	GPIO_INIT(U,    4,   IN),
+	GPIO_INIT(U,    5,   IN),
+	GPIO_INIT(U,    6,   IN),
+	GPIO_INIT(V,    0,   IN),
+	GPIO_INIT(V,    1,   IN),
+	GPIO_INIT(W,    3,   IN),
+	GPIO_INIT(X,    1,   IN),
+	GPIO_INIT(X,    3,   IN),
+	GPIO_INIT(X,    4,   IN),
+	GPIO_INIT(X,    7,   OUT0),
+	GPIO_INIT(CC,   5,   OUT0),
 };
 
 #define PINCFG(_pingrp, _mux, _pull, _tri, _io, _od, _rcv_sel)	\
diff --git a/board/ronetix/pm9261/pm9261.c b/board/ronetix/pm9261/pm9261.c
index 3cc01cb..e2cb94e 100644
--- a/board/ronetix/pm9261/pm9261.c
+++ b/board/ronetix/pm9261/pm9261.c
@@ -194,7 +194,7 @@
 
 	nand_size = 0;
 	for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
-		nand_size += nand_info[i].size;
+		nand_size += nand_info[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 276ff80..e9f9b67 100644
--- a/board/ronetix/pm9263/pm9263.c
+++ b/board/ronetix/pm9263/pm9263.c
@@ -293,7 +293,7 @@
 
 	nand_size = 0;
 	for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
-		nand_size += nand_info[i].size;
+		nand_size += nand_info[i]->size;
 
 	flash_size = 0;
 	for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++)
diff --git a/board/socrates/nand.c b/board/socrates/nand.c
index 15e6ea6..a67d812 100644
--- a/board/socrates/nand.c
+++ b/board/socrates/nand.c
@@ -48,7 +48,7 @@
 static void sc_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
 {
 	int i;
-	struct nand_chip *this = mtd->priv;
+	struct nand_chip *this = mtd_to_nand(mtd);
 
 	for (i = 0; i < len; i++) {
 		out_be32(this->IO_ADDR_W,
@@ -88,7 +88,7 @@
 static void sc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
 {
 	int i;
-	struct nand_chip *this = mtd->priv;
+	struct nand_chip *this = mtd_to_nand(mtd);
 	int val;
 
 	val = (state & FPGA_NAND_ENABLE) | FPGA_NAND_CMD_READ;
@@ -105,7 +105,7 @@
  */
 static int sc_nand_device_ready(struct mtd_info *mtdinfo)
 {
-	struct nand_chip *this = mtdinfo->priv;
+	struct nand_chip *this = mtd_to_nand(mtdinfo);
 
 	if (in_be32(this->IO_ADDR_W) & FPGA_NAND_BUSY)
 		return 0; /* busy */
diff --git a/board/toradex/colibri_t20/colibri_t20.c b/board/toradex/colibri_t20/colibri_t20.c
index 879f25a..68fbf49 100644
--- a/board/toradex/colibri_t20/colibri_t20.c
+++ b/board/toradex/colibri_t20/colibri_t20.c
@@ -103,11 +103,11 @@
 	pinmux_tristate_disable(PMUX_PINGRP_DTE);
 
 	/* Reset ASIX using LAN_RESET */
-	gpio_request(GPIO_PV4, "LAN_RESET");
-	gpio_direction_output(GPIO_PV4, 0);
+	gpio_request(TEGRA_GPIO(V, 4), "LAN_RESET");
+	gpio_direction_output(TEGRA_GPIO(V, 4), 0);
 	pinmux_tristate_disable(PMUX_PINGRP_GPV);
 	udelay(5);
-	gpio_set_value(GPIO_PV4, 1);
+	gpio_set_value(TEGRA_GPIO(V, 4), 1);
 
 	/* USBH_PEN: USB 1 aka Tegra USB port 3 VBus */
 	pinmux_tristate_disable(PMUX_PINGRP_SPIG);
diff --git a/board/toradex/colibri_t30/colibri_t30.c b/board/toradex/colibri_t30/colibri_t30.c
index 44b5beb..e32362a 100644
--- a/board/toradex/colibri_t30/colibri_t30.c
+++ b/board/toradex/colibri_t30/colibri_t30.c
@@ -47,8 +47,8 @@
 void pin_mux_usb(void)
 {
 	/* Reset ASIX using LAN_RESET */
-	gpio_request(GPIO_PDD0, "LAN_RESET");
-	gpio_direction_output(GPIO_PDD0, 0);
+	gpio_request(TEGRA_GPIO(DD, 0), "LAN_RESET");
+	gpio_direction_output(TEGRA_GPIO(DD, 0), 0);
 	udelay(5);
-	gpio_set_value(GPIO_PDD0, 1);
+	gpio_set_value(TEGRA_GPIO(DD, 0), 1);
 }
diff --git a/board/xes/common/actl_nand.c b/board/xes/common/actl_nand.c
index bf896fe..d1f3668 100644
--- a/board/xes/common/actl_nand.c
+++ b/board/xes/common/actl_nand.c
@@ -16,7 +16,7 @@
  */
 static void nand_addr_hwcontrol(struct mtd_info *mtd, int cmd, uint ctrl)
 {
-	struct nand_chip *this = mtd->priv;
+	struct nand_chip *this = mtd_to_nand(mtd);
 	ulong IO_ADDR_W;
 
 	if (ctrl & NAND_CTRL_CHANGE) {
diff --git a/board/xilinx/microblaze-generic/Kconfig b/board/xilinx/microblaze-generic/Kconfig
index 461d7dc..02ac65c 100644
--- a/board/xilinx/microblaze-generic/Kconfig
+++ b/board/xilinx/microblaze-generic/Kconfig
@@ -9,4 +9,28 @@
 config SYS_CONFIG_NAME
 	default "microblaze-generic"
 
+config XILINX_MICROBLAZE0_USE_MSR_INSTR
+	int "USE_MSR_INSTR range (0:1)"
+	default 0
+
+config XILINX_MICROBLAZE0_USE_PCMP_INSTR
+	int "USE_PCMP_INSTR range (0:1)"
+	default 0
+
+config XILINX_MICROBLAZE0_USE_BARREL
+	int "USE_BARREL range (0:1)"
+	default 0
+
+config XILINX_MICROBLAZE0_USE_DIV
+	int "USE_DIV range (0:1)"
+	default 0
+
+config XILINX_MICROBLAZE0_USE_HW_MUL
+	int "USE_HW_MUL values (0=NONE, 1=MUL32, 2=MUL64)"
+	default 0
+
+config XILINX_MICROBLAZE0_HW_VER
+	string "Core version number"
+	default 7.10.d
+
 endif
diff --git a/board/xilinx/microblaze-generic/config.mk b/board/xilinx/microblaze-generic/config.mk
index 95ef9c0..1dee2d6 100644
--- a/board/xilinx/microblaze-generic/config.mk
+++ b/board/xilinx/microblaze-generic/config.mk
@@ -1,16 +1,20 @@
 #
-# (C) Copyright 2007 Michal Simek
+# (C) Copyright 2007 - 2016 Michal Simek
 #
-# Michal  SIMEK <monstr@monstr.eu>
+# Michal SIMEK <monstr@monstr.eu>
 #
 # SPDX-License-Identifier:	GPL-2.0+
 #
-# CAUTION: This file is a faked configuration !!!
-#          There is no real target for the microblaze-generic
-#          configuration. You have to replace this file with
-#          the generated file from your Xilinx design flow.
-#
+
+CPU_VER := $(shell echo $(CONFIG_XILINX_MICROBLAZE0_HW_VER))
+
+# USE_HW_MUL can be 0, 1, or 2, defining a hierarchy of HW Mul support.
+CPUFLAGS-$(subst 1,,$(CONFIG_XILINX_MICROBLAZE0_USE_HW_MUL)) += -mxl-multiply-high
+CPUFLAGS-$(CONFIG_XILINX_MICROBLAZE0_USE_HW_MUL) += -mno-xl-soft-mul
+CPUFLAGS-$(CONFIG_XILINX_MICROBLAZE0_USE_DIV) += -mno-xl-soft-div
+CPUFLAGS-$(CONFIG_XILINX_MICROBLAZE0_USE_BARREL) += -mxl-barrel-shift
+CPUFLAGS-$(CONFIG_XILINX_MICROBLAZE0_USE_PCMP_INSTR) += -mxl-pattern-compare
+
+CPUFLAGS-1 += $(call cc-option,-mcpu=v$(CPU_VER))
 
-PLATFORM_CPPFLAGS += -mno-xl-soft-mul
-PLATFORM_CPPFLAGS += -mno-xl-soft-div
-PLATFORM_CPPFLAGS += -mxl-barrel-shift
+PLATFORM_CPPFLAGS += $(CPUFLAGS-1) $(CPUFLAGS-2)
diff --git a/board/xilinx/microblaze-generic/xparameters.h b/board/xilinx/microblaze-generic/xparameters.h
index dc5645b..ee7d087 100644
--- a/board/xilinx/microblaze-generic/xparameters.h
+++ b/board/xilinx/microblaze-generic/xparameters.h
@@ -14,7 +14,6 @@
 #define XILINX_BOARD_NAME	microblaze-generic
 
 /* Microblaze is microblaze_0 */
-#define XILINX_USE_MSR_INSTR	1
 #define XILINX_FSL_NUMBER	3
 
 /* GPIO is LEDs_4Bit*/
diff --git a/board/xilinx/zynqmp/zynqmp.c b/board/xilinx/zynqmp/zynqmp.c
index 4623cd4..f15dc5d 100644
--- a/board/xilinx/zynqmp/zynqmp.c
+++ b/board/xilinx/zynqmp/zynqmp.c
@@ -9,6 +9,7 @@
 #include <sata.h>
 #include <ahci.h>
 #include <scsi.h>
+#include <malloc.h>
 #include <asm/arch/clk.h>
 #include <asm/arch/hardware.h>
 #include <asm/arch/sys_proto.h>
@@ -214,6 +215,13 @@
 {
 	u32 reg = 0;
 	u8 bootmode;
+	const char *mode;
+	char *new_targets;
+
+	if (!(gd->flags & GD_FLG_ENV_DEFAULT)) {
+		debug("Saved variables - Skipping\n");
+		return 0;
+	}
 
 	reg = readl(&crlapb_base->boot_mode);
 	bootmode = reg & BOOT_MODES_MASK;
@@ -222,37 +230,49 @@
 	switch (bootmode) {
 	case JTAG_MODE:
 		puts("JTAG_MODE\n");
-		setenv("modeboot", "jtagboot");
+		mode = "pxe dhcp";
 		break;
 	case QSPI_MODE_24BIT:
 	case QSPI_MODE_32BIT:
-		setenv("modeboot", "qspiboot");
+		mode = "qspi0";
 		puts("QSPI_MODE\n");
 		break;
 	case EMMC_MODE:
 		puts("EMMC_MODE\n");
-		setenv("modeboot", "sdboot");
+		mode = "mmc0";
 		break;
 	case SD_MODE:
 		puts("SD_MODE\n");
-		setenv("modeboot", "sdboot");
+		mode = "mmc0";
 		break;
 	case SD_MODE1:
 		puts("SD_MODE1\n");
 #if defined(CONFIG_ZYNQ_SDHCI0) && defined(CONFIG_ZYNQ_SDHCI1)
-		setenv("sdbootdev", "1");
+		mode = "mmc1";
+#else
+		mode = "mmc0";
 #endif
-		setenv("modeboot", "sdboot");
 		break;
 	case NAND_MODE:
 		puts("NAND_MODE\n");
-		setenv("modeboot", "nandboot");
+		mode = "nand0";
 		break;
 	default:
+		mode = "";
 		printf("Invalid Boot Mode:0x%x\n", bootmode);
 		break;
 	}
 
+	/*
+	 * One terminating char + one byte for space between mode
+	 * and default boot_targets
+	 */
+	new_targets = calloc(1, strlen(mode) +
+				strlen(getenv("boot_targets")) + 2);
+
+	sprintf(new_targets, "%s %s", mode, getenv("boot_targets"));
+	setenv("boot_targets", new_targets);
+
 	return 0;
 }
 
diff --git a/cmd/bootm.c b/cmd/bootm.c
index ee3b460..f5e91f4 100644
--- a/cmd/bootm.c
+++ b/cmd/bootm.c
@@ -372,8 +372,8 @@
 #endif
 
 #if defined(CONFIG_CMD_IMLS_NAND)
-static int nand_imls_legacyimage(nand_info_t *nand, int nand_dev, loff_t off,
-		size_t len)
+static int nand_imls_legacyimage(struct mtd_info *mtd, int nand_dev,
+				 loff_t off, size_t len)
 {
 	void *imgdata;
 	int ret;
@@ -386,8 +386,7 @@
 		return -ENOMEM;
 	}
 
-	ret = nand_read_skip_bad(nand, off, &len,
-			imgdata);
+	ret = nand_read_skip_bad(mtd, off, &len, imgdata);
 	if (ret < 0 && ret != -EUCLEAN) {
 		free(imgdata);
 		return ret;
@@ -413,8 +412,8 @@
 	return 0;
 }
 
-static int nand_imls_fitimage(nand_info_t *nand, int nand_dev, loff_t off,
-		size_t len)
+static int nand_imls_fitimage(struct mtd_info *mtd, int nand_dev, loff_t off,
+			      size_t len)
 {
 	void *imgdata;
 	int ret;
@@ -427,8 +426,7 @@
 		return -ENOMEM;
 	}
 
-	ret = nand_read_skip_bad(nand, off, &len,
-			imgdata);
+	ret = nand_read_skip_bad(mtd, off, &len, imgdata);
 	if (ret < 0 && ret != -EUCLEAN) {
 		free(imgdata);
 		return ret;
@@ -449,7 +447,7 @@
 
 static int do_imls_nand(void)
 {
-	nand_info_t *nand;
+	struct mtd_info *mtd;
 	int nand_dev = nand_curr_device;
 	size_t len;
 	loff_t off;
@@ -463,20 +461,20 @@
 	printf("\n");
 
 	for (nand_dev = 0; nand_dev < CONFIG_SYS_MAX_NAND_DEVICE; nand_dev++) {
-		nand = &nand_info[nand_dev];
-		if (!nand->name || !nand->size)
+		mtd = nand_info[nand_dev];
+		if (!mtd->name || !mtd->size)
 			continue;
 
-		for (off = 0; off < nand->size; off += nand->erasesize) {
+		for (off = 0; off < mtd->size; off += mtd->erasesize) {
 			const image_header_t *header;
 			int ret;
 
-			if (nand_block_isbad(nand, off))
+			if (nand_block_isbad(mtd, off))
 				continue;
 
 			len = sizeof(buffer);
 
-			ret = nand_read(nand, off, &len, (u8 *)buffer);
+			ret = nand_read(mtd, off, &len, (u8 *)buffer);
 			if (ret < 0 && ret != -EUCLEAN) {
 				printf("NAND read error %d at offset %08llX\n",
 						ret, off);
@@ -489,13 +487,13 @@
 				header = (const image_header_t *)buffer;
 
 				len = image_get_image_size(header);
-				nand_imls_legacyimage(nand, nand_dev, off, len);
+				nand_imls_legacyimage(mtd, nand_dev, off, len);
 				break;
 #endif
 #if defined(CONFIG_FIT)
 			case IMAGE_FORMAT_FIT:
 				len = fit_get_size(buffer);
-				nand_imls_fitimage(nand, nand_dev, off, len);
+				nand_imls_fitimage(mtd, nand_dev, off, len);
 				break;
 #endif
 			}
diff --git a/cmd/jffs2.c b/cmd/jffs2.c
index 0b2eefa..f00d53a 100644
--- a/cmd/jffs2.c
+++ b/cmd/jffs2.c
@@ -167,7 +167,7 @@
 	} 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;
+			*size = nand_info[num]->size;
 			return 0;
 		}
 
@@ -242,11 +242,11 @@
 static inline u32 get_part_sector_size_nand(struct mtdids *id)
 {
 #if defined(CONFIG_JFFS2_NAND) && defined(CONFIG_CMD_NAND)
-	nand_info_t *nand;
+	struct mtd_info *mtd;
 
-	nand = &nand_info[id->num];
+	mtd = nand_info[id->num];
 
-	return nand->erasesize;
+	return mtd->erasesize;
 #else
 	BUG();
 	return 0;
diff --git a/cmd/nand.c b/cmd/nand.c
index a6b67e2..583a18f 100644
--- a/cmd/nand.c
+++ b/cmd/nand.c
@@ -38,7 +38,8 @@
 		      u8 *part_num, struct part_info **part);
 #endif
 
-static int nand_dump(nand_info_t *nand, ulong off, int only_oob, int repeat)
+static int nand_dump(struct mtd_info *mtd, ulong off, int only_oob,
+		     int repeat)
 {
 	int i;
 	u_char *datbuf, *oobbuf, *p;
@@ -46,32 +47,32 @@
 	int ret = 0;
 
 	if (repeat)
-		off = last + nand->writesize;
+		off = last + mtd->writesize;
 
 	last = off;
 
-	datbuf = memalign(ARCH_DMA_MINALIGN, nand->writesize);
+	datbuf = memalign(ARCH_DMA_MINALIGN, mtd->writesize);
 	if (!datbuf) {
 		puts("No memory for page buffer\n");
 		return 1;
 	}
 
-	oobbuf = memalign(ARCH_DMA_MINALIGN, nand->oobsize);
+	oobbuf = memalign(ARCH_DMA_MINALIGN, mtd->oobsize);
 	if (!oobbuf) {
 		puts("No memory for page buffer\n");
 		ret = 1;
 		goto free_dat;
 	}
-	off &= ~(nand->writesize - 1);
+	off &= ~(mtd->writesize - 1);
 	loff_t addr = (loff_t) off;
 	struct mtd_oob_ops ops;
 	memset(&ops, 0, sizeof(ops));
 	ops.datbuf = datbuf;
 	ops.oobbuf = oobbuf;
-	ops.len = nand->writesize;
-	ops.ooblen = nand->oobsize;
+	ops.len = mtd->writesize;
+	ops.ooblen = mtd->oobsize;
 	ops.mode = MTD_OPS_RAW;
-	i = mtd_read_oob(nand, addr, &ops);
+	i = mtd_read_oob(mtd, addr, &ops);
 	if (i < 0) {
 		printf("Error (%d) reading page %08lx\n", i, off);
 		ret = 1;
@@ -80,7 +81,7 @@
 	printf("Page %08lx dump:\n", off);
 
 	if (!only_oob) {
-		i = nand->writesize >> 4;
+		i = mtd->writesize >> 4;
 		p = datbuf;
 
 		while (i--) {
@@ -94,7 +95,7 @@
 	}
 
 	puts("OOB:\n");
-	i = nand->oobsize >> 3;
+	i = mtd->oobsize >> 3;
 	p = oobbuf;
 	while (i--) {
 		printf("\t%02x %02x %02x %02x %02x %02x %02x %02x\n",
@@ -115,7 +116,7 @@
 static int set_dev(int dev)
 {
 	if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE ||
-	    !nand_info[dev].name) {
+	    !nand_info[dev]->name) {
 		puts("No such device\n");
 		return -1;
 	}
@@ -123,12 +124,12 @@
 	if (nand_curr_device == dev)
 		return 0;
 
-	printf("Device %d: %s", dev, nand_info[dev].name);
+	printf("Device %d: %s", dev, nand_info[dev]->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(nand_info[dev]->priv, dev);
 #endif
 
 	return 0;
@@ -152,32 +153,32 @@
 		((status & NAND_LOCK_STATUS_UNLOCK) ?  "UNLOCK " : ""));
 }
 
-static void do_nand_status(nand_info_t *nand)
+static void do_nand_status(struct mtd_info *mtd)
 {
 	ulong block_start = 0;
 	ulong off;
 	int last_status = -1;
 
-	struct nand_chip *nand_chip = nand->priv;
+	struct nand_chip *nand_chip = mtd_to_nand(mtd);
 	/* check the WP bit */
-	nand_chip->cmdfunc(nand, NAND_CMD_STATUS, -1, -1);
+	nand_chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
 	printf("device is %swrite protected\n",
-		(nand_chip->read_byte(nand) & 0x80 ?
-		"NOT " : ""));
+		(nand_chip->read_byte(mtd) & 0x80 ?
+		 "NOT " : ""));
 
-	for (off = 0; off < nand->size; off += nand->erasesize) {
-		int s = nand_get_lock_status(nand, off);
+	for (off = 0; off < mtd->size; off += mtd->erasesize) {
+		int s = nand_get_lock_status(mtd, off);
 
 		/* print message only if status has changed */
 		if (s != last_status && off != 0) {
-			print_status(block_start, off, nand->erasesize,
+			print_status(block_start, off, mtd->erasesize,
 					last_status);
 			block_start = off;
 		}
 		last_status = s;
 	}
 	/* Print the last block info */
-	print_status(block_start, off, nand->erasesize, last_status);
+	print_status(block_start, off, mtd->erasesize, last_status);
 }
 #endif
 
@@ -188,10 +189,10 @@
 {
 	int ret;
 	uint32_t oob_buf[ENV_OFFSET_SIZE/sizeof(uint32_t)];
-	nand_info_t *nand = &nand_info[0];
+	struct mtd_info *mtd = nand_info[0];
 	char *cmd = argv[1];
 
-	if (CONFIG_SYS_MAX_NAND_DEVICE == 0 || !nand->name) {
+	if (CONFIG_SYS_MAX_NAND_DEVICE == 0 || !mtd->name) {
 		puts("no devices available\n");
 		return 1;
 	}
@@ -199,7 +200,7 @@
 	set_dev(0);
 
 	if (!strcmp(cmd, "get")) {
-		ret = get_nand_env_oob(nand, &nand_env_oob_offset);
+		ret = get_nand_env_oob(mtd, &nand_env_oob_offset);
 		if (ret)
 			return 1;
 
@@ -215,7 +216,7 @@
 
 		/* 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, nand_info[idx]->size)) {
 			puts("Offset or partition name expected\n");
 			return 1;
 		}
@@ -229,15 +230,15 @@
 			return 1;
 		}
 
-		if (nand->oobavail < ENV_OFFSET_SIZE) {
+		if (mtd->oobavail < ENV_OFFSET_SIZE) {
 			printf("Insufficient available OOB bytes:\n"
 			       "%d OOB bytes available but %d required for "
 			       "env.oob support\n",
-			       nand->oobavail, ENV_OFFSET_SIZE);
+			       mtd->oobavail, ENV_OFFSET_SIZE);
 			return 1;
 		}
 
-		if ((addr & (nand->erasesize - 1)) != 0) {
+		if ((addr & (mtd->erasesize - 1)) != 0) {
 			printf("Environment offset must be block-aligned\n");
 			return 1;
 		}
@@ -249,15 +250,15 @@
 		ops.oobbuf = (void *) oob_buf;
 
 		oob_buf[0] = ENV_OOB_MARKER;
-		oob_buf[1] = addr / nand->erasesize;
+		oob_buf[1] = addr / mtd->erasesize;
 
-		ret = nand->write_oob(nand, ENV_OFFSET_SIZE, &ops);
+		ret = mtd->write_oob(mtd, ENV_OFFSET_SIZE, &ops);
 		if (ret) {
 			printf("Error writing OOB block 0\n");
 			return ret;
 		}
 
-		ret = get_nand_env_oob(nand, &nand_env_oob_offset);
+		ret = get_nand_env_oob(mtd, &nand_env_oob_offset);
 		if (ret) {
 			printf("Error reading env offset in OOB\n");
 			return ret;
@@ -283,29 +284,29 @@
 
 static void nand_print_and_set_info(int idx)
 {
-	nand_info_t *nand = &nand_info[idx];
-	struct nand_chip *chip = nand->priv;
+	struct mtd_info *mtd = nand_info[idx];
+	struct nand_chip *chip = mtd_to_nand(mtd);
 
 	printf("Device %d: ", idx);
 	if (chip->numchips > 1)
 		printf("%dx ", chip->numchips);
 	printf("%s, sector size %u KiB\n",
-	       nand->name, nand->erasesize >> 10);
-	printf("  Page size   %8d b\n", nand->writesize);
-	printf("  OOB size    %8d b\n", nand->oobsize);
-	printf("  Erase size  %8d b\n", nand->erasesize);
+	       mtd->name, mtd->erasesize >> 10);
+	printf("  Page size   %8d b\n", mtd->writesize);
+	printf("  OOB size    %8d b\n", mtd->oobsize);
+	printf("  Erase size  %8d b\n", mtd->erasesize);
 	printf("  subpagesize %8d b\n", chip->subpagesize);
 	printf("  options     0x%8x\n", chip->options);
 	printf("  bbt options 0x%8x\n", chip->bbt_options);
 
 	/* Set geometry info */
-	setenv_hex("nand_writesize", nand->writesize);
-	setenv_hex("nand_oobsize", nand->oobsize);
-	setenv_hex("nand_erasesize", nand->erasesize);
+	setenv_hex("nand_writesize", mtd->writesize);
+	setenv_hex("nand_oobsize", mtd->oobsize);
+	setenv_hex("nand_erasesize", mtd->erasesize);
 }
 
-static int raw_access(nand_info_t *nand, ulong addr, loff_t off, ulong count,
-			int read)
+static int raw_access(struct mtd_info *mtd, ulong addr, loff_t off,
+		      ulong count, int read)
 {
 	int ret = 0;
 
@@ -313,18 +314,18 @@
 		/* Raw access */
 		mtd_oob_ops_t ops = {
 			.datbuf = (u8 *)addr,
-			.oobbuf = ((u8 *)addr) + nand->writesize,
-			.len = nand->writesize,
-			.ooblen = nand->oobsize,
+			.oobbuf = ((u8 *)addr) + mtd->writesize,
+			.len = mtd->writesize,
+			.ooblen = mtd->oobsize,
 			.mode = MTD_OPS_RAW
 		};
 
 		if (read) {
-			ret = mtd_read_oob(nand, off, &ops);
+			ret = mtd_read_oob(mtd, off, &ops);
 		} else {
-			ret = mtd_write_oob(nand, off, &ops);
+			ret = mtd_write_oob(mtd, off, &ops);
 			if (!ret)
-				ret = nand_verify_page_oob(nand, &ops, off);
+				ret = nand_verify_page_oob(mtd, &ops, off);
 		}
 
 		if (ret) {
@@ -333,8 +334,8 @@
 			break;
 		}
 
-		addr += nand->writesize + nand->oobsize;
-		off += nand->writesize;
+		addr += mtd->writesize + mtd->oobsize;
+		off += mtd->writesize;
 	}
 
 	return ret;
@@ -348,18 +349,18 @@
 	/* We grab the nand info object here fresh because this is usually
 	 * called after arg_off_size() which can change the value of dev.
 	 */
-	nand_info_t *nand = &nand_info[dev];
+	struct mtd_info *mtd = nand_info[dev];
 	loff_t maxoffset = offset + *size;
 	int badblocks = 0;
 
 	/* count badblocks in NAND from offset to offset + size */
-	for (; offset < maxoffset; offset += nand->erasesize) {
-		if (nand_block_isbad(nand, offset))
+	for (; offset < maxoffset; offset += mtd->erasesize) {
+		if (nand_block_isbad(mtd, offset))
 			badblocks++;
 	}
 	/* adjust size if any bad blocks found */
 	if (badblocks) {
-		*size -= badblocks * nand->erasesize;
+		*size -= badblocks * mtd->erasesize;
 		printf("size adjusted to 0x%llx (%d bad blocks)\n",
 		       (unsigned long long)*size, badblocks);
 	}
@@ -371,7 +372,7 @@
 	ulong addr;
 	loff_t off, size, maxsize;
 	char *cmd, *s;
-	nand_info_t *nand;
+	struct mtd_info *mtd;
 #ifdef CONFIG_SYS_NAND_QUIET
 	int quiet = CONFIG_SYS_NAND_QUIET;
 #else
@@ -398,7 +399,7 @@
 
 		putc('\n');
 		for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) {
-			if (nand_info[i].name)
+			if (nand_info[i]->name)
 				nand_print_and_set_info(i);
 		}
 		return 0;
@@ -433,16 +434,16 @@
 	 * for another device is to be used.
 	 */
 	if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE ||
-	    !nand_info[dev].name) {
+	    !nand_info[dev]->name) {
 		puts("\nno devices available\n");
 		return 1;
 	}
-	nand = &nand_info[dev];
+	mtd = nand_info[dev];
 
 	if (strcmp(cmd, "bad") == 0) {
 		printf("\nDevice %d bad blocks:\n", dev);
-		for (off = 0; off < nand->size; off += nand->erasesize)
-			if (nand_block_isbad(nand, off))
+		for (off = 0; off < mtd->size; off += mtd->erasesize)
+			if (nand_block_isbad(mtd, off))
 				printf("  %08llx\n", (unsigned long long)off);
 		return 0;
 	}
@@ -496,13 +497,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)
+				     nand_info[dev]->size) != 0)
 			return 1;
 
 		if (set_dev(dev))
 			return 1;
 
-		nand = &nand_info[dev];
+		mtd = nand_info[dev];
 
 		memset(&opts, 0, sizeof(opts));
 		opts.offset = off;
@@ -524,7 +525,7 @@
 				}
 			}
 		}
-		ret = nand_erase_opts(nand, &opts);
+		ret = nand_erase_opts(mtd, &opts);
 		printf("%s\n", ret ? "ERROR" : "OK");
 
 		return ret == 0 ? 0 : 1;
@@ -535,7 +536,7 @@
 			goto usage;
 
 		off = (int)simple_strtoul(argv[2], NULL, 16);
-		ret = nand_dump(nand, off, !strcmp(&cmd[4], ".oob"), repeat);
+		ret = nand_dump(mtd, off, !strcmp(&cmd[4], ".oob"), repeat);
 
 		return ret == 0 ? 1 : 0;
 	}
@@ -561,30 +562,30 @@
 
 			if (mtd_arg_off(argv[3], &dev, &off, &size, &maxsize,
 					MTD_DEV_TYPE_NAND,
-					nand_info[dev].size))
+					nand_info[dev]->size))
 				return 1;
 
 			if (set_dev(dev))
 				return 1;
 
-			nand = &nand_info[dev];
+			mtd = nand_info[dev];
 
 			if (argc > 4 && !str2long(argv[4], &pagecount)) {
 				printf("'%s' is not a number\n", argv[4]);
 				return 1;
 			}
 
-			if (pagecount * nand->writesize > size) {
+			if (pagecount * mtd->writesize > size) {
 				puts("Size exceeds partition or device limit\n");
 				return -1;
 			}
 
-			rwsize = pagecount * (nand->writesize + nand->oobsize);
+			rwsize = pagecount * (mtd->writesize + mtd->oobsize);
 		} else {
 			if (mtd_arg_off_size(argc - 3, argv + 3, &dev, &off,
 					     &size, &maxsize,
 					     MTD_DEV_TYPE_NAND,
-					     nand_info[dev].size) != 0)
+					     nand_info[dev]->size) != 0)
 				return 1;
 
 			if (set_dev(dev))
@@ -596,16 +597,16 @@
 			rwsize = size;
 		}
 
-		nand = &nand_info[dev];
+		mtd = nand_info[dev];
 
 		if (!s || !strcmp(s, ".jffs2") ||
 		    !strcmp(s, ".e") || !strcmp(s, ".i")) {
 			if (read)
-				ret = nand_read_skip_bad(nand, off, &rwsize,
+				ret = nand_read_skip_bad(mtd, off, &rwsize,
 							 NULL, maxsize,
 							 (u_char *)addr);
 			else
-				ret = nand_write_skip_bad(nand, off, &rwsize,
+				ret = nand_write_skip_bad(mtd, off, &rwsize,
 							  NULL, maxsize,
 							  (u_char *)addr,
 							  WITH_WR_VERIFY);
@@ -615,7 +616,7 @@
 				printf("Unknown nand command suffix '%s'\n", s);
 				return 1;
 			}
-			ret = nand_write_skip_bad(nand, off, &rwsize, NULL,
+			ret = nand_write_skip_bad(mtd, off, &rwsize, NULL,
 						maxsize, (u_char *)addr,
 						WITH_DROP_FFS | WITH_WR_VERIFY);
 #endif
@@ -628,11 +629,11 @@
 			};
 
 			if (read)
-				ret = mtd_read_oob(nand, off, &ops);
+				ret = mtd_read_oob(mtd, off, &ops);
 			else
-				ret = mtd_write_oob(nand, off, &ops);
+				ret = mtd_write_oob(mtd, off, &ops);
 		} else if (raw) {
-			ret = raw_access(nand, addr, off, pagecount, read);
+			ret = raw_access(mtd, addr, off, pagecount, read);
 		} else {
 			printf("Unknown nand command suffix '%s'.\n", s);
 			return 1;
@@ -655,8 +656,8 @@
 		}
 
 		printf("\nNAND torture: device %d offset 0x%llx size 0x%x\n",
-			dev, off, nand->erasesize);
-		ret = nand_torture(nand, off);
+			dev, off, mtd->erasesize);
+		ret = nand_torture(mtd, off);
 		printf(" %s\n", ret ? "Failed" : "Passed");
 
 		return ret == 0 ? 0 : 1;
@@ -673,7 +674,7 @@
 		while (argc > 0) {
 			addr = simple_strtoul(*argv, NULL, 16);
 
-			if (mtd_block_markbad(nand, addr)) {
+			if (mtd_block_markbad(mtd, addr)) {
 				printf("block 0x%08lx NOT marked "
 					"as bad! ERROR %d\n",
 					addr, ret);
@@ -705,9 +706,9 @@
 				status = 1;
 		}
 		if (status) {
-			do_nand_status(nand);
+			do_nand_status(mtd);
 		} else {
-			if (!nand_lock(nand, tight)) {
+			if (!nand_lock(mtd, tight)) {
 				puts("NAND flash successfully locked\n");
 			} else {
 				puts("Error locking NAND flash\n");
@@ -727,13 +728,13 @@
 
 		if (mtd_arg_off_size(argc - 2, argv + 2, &dev, &off, &size,
 				     &maxsize, MTD_DEV_TYPE_NAND,
-				     nand_info[dev].size) < 0)
+				     nand_info[dev]->size) < 0)
 			return 1;
 
 		if (set_dev(dev))
 			return 1;
 
-		if (!nand_unlock(&nand_info[dev], off, size, allexcept)) {
+		if (!nand_unlock(nand_info[dev], off, size, allexcept)) {
 			puts("NAND flash successfully unlocked\n");
 		} else {
 			puts("Error unlocking NAND flash, "
@@ -801,7 +802,7 @@
 	"NAND sub-system", nand_help_text
 );
 
-static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand,
+static int nand_load_image(cmd_tbl_t *cmdtp, struct mtd_info *mtd,
 			   ulong offset, ulong addr, char *cmd)
 {
 	int r;
@@ -822,11 +823,11 @@
 		return 1;
 	}
 
-	printf("\nLoading from %s, offset 0x%lx\n", nand->name, offset);
+	printf("\nLoading from %s, offset 0x%lx\n", mtd->name, offset);
 
-	cnt = nand->writesize;
-	r = nand_read_skip_bad(nand, offset, &cnt, NULL, nand->size,
-			(u_char *)addr);
+	cnt = mtd->writesize;
+	r = nand_read_skip_bad(mtd, offset, &cnt, NULL, mtd->size,
+			       (u_char *)addr);
 	if (r) {
 		puts("** Read error\n");
 		bootstage_error(BOOTSTAGE_ID_NAND_HDR_READ);
@@ -860,8 +861,8 @@
 	}
 	bootstage_mark(BOOTSTAGE_ID_NAND_TYPE);
 
-	r = nand_read_skip_bad(nand, offset, &cnt, NULL, nand->size,
-			(u_char *)addr);
+	r = nand_read_skip_bad(mtd, offset, &cnt, NULL, mtd->size,
+			       (u_char *)addr);
 	if (r) {
 		puts("** Read error\n");
 		bootstage_error(BOOTSTAGE_ID_NAND_READ);
@@ -914,7 +915,7 @@
 				addr = simple_strtoul(argv[1], NULL, 16);
 			else
 				addr = CONFIG_SYS_LOAD_ADDR;
-			return nand_load_image(cmdtp, &nand_info[dev->id->num],
+			return nand_load_image(cmdtp, nand_info[dev->id->num],
 					       part->offset, addr, argv[0]);
 		}
 	}
@@ -957,14 +958,14 @@
 
 	idx = simple_strtoul(boot_device, NULL, 16);
 
-	if (idx < 0 || idx >= CONFIG_SYS_MAX_NAND_DEVICE || !nand_info[idx].name) {
+	if (idx < 0 || idx >= CONFIG_SYS_MAX_NAND_DEVICE || !nand_info[idx]->name) {
 		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, nand_info[idx], offset, addr, argv[0]);
 }
 
 U_BOOT_CMD(nboot, 4, 1, do_nandboot,
diff --git a/common/env_common.c b/common/env_common.c
index af59c72..13db7dc 100644
--- a/common/env_common.c
+++ b/common/env_common.c
@@ -123,6 +123,7 @@
 		error("Environment import failed: errno = %d\n", errno);
 
 	gd->flags |= GD_FLG_ENV_READY;
+	gd->flags |= GD_FLG_ENV_DEFAULT;
 }
 
 
diff --git a/common/env_nand.c b/common/env_nand.c
index b32eeac..fc99a5e 100644
--- a/common/env_nand.c
+++ b/common/env_nand.c
@@ -132,15 +132,15 @@
 	size_t blocksize, len;
 	u_char *char_ptr;
 
-	blocksize = nand_info[0].erasesize;
+	blocksize = nand_info[0]->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(nand_info[0], offset)) {
 			offset += blocksize;
 		} else {
 			char_ptr = &buf[amount_saved];
-			if (nand_write(&nand_info[0], offset, &len, char_ptr))
+			if (nand_write(nand_info[0], offset, &len, char_ptr))
 				return 1;
 
 			offset += blocksize;
@@ -164,7 +164,7 @@
 	int ret = 0;
 
 	printf("Erasing %s...\n", location->name);
-	if (nand_erase_opts(&nand_info[0], &location->erase_opts))
+	if (nand_erase_opts(nand_info[0], &location->erase_opts))
 		return 1;
 
 	printf("Writing to %s... ", location->name);
@@ -247,20 +247,20 @@
 	size_t blocksize, len;
 	u_char *char_ptr;
 
-	blocksize = nand_info[0].erasesize;
+	blocksize = nand_info[0]->erasesize;
 	if (!blocksize)
 		return 1;
 
 	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(nand_info[0], offset)) {
 			offset += blocksize;
 		} else {
 			char_ptr = &buf[amount_loaded];
-			if (nand_read_skip_bad(&nand_info[0], offset,
+			if (nand_read_skip_bad(nand_info[0], offset,
 					       &len, NULL,
-					       nand_info[0].size, char_ptr))
+					       nand_info[0]->size, char_ptr))
 				return 1;
 
 			offset += blocksize;
@@ -276,7 +276,7 @@
 #endif /* #if defined(CONFIG_SPL_BUILD) */
 
 #ifdef CONFIG_ENV_OFFSET_OOB
-int get_nand_env_oob(nand_info_t *nand, unsigned long *result)
+int get_nand_env_oob(struct mtd_info *mtd, unsigned long *result)
 {
 	struct mtd_oob_ops ops;
 	uint32_t oob_buf[ENV_OFFSET_SIZE / sizeof(uint32_t)];
@@ -288,14 +288,14 @@
 	ops.ooblen	= ENV_OFFSET_SIZE;
 	ops.oobbuf	= (void *)oob_buf;
 
-	ret = nand->read_oob(nand, ENV_OFFSET_SIZE, &ops);
+	ret = mtd->read_oob(mtd, ENV_OFFSET_SIZE, &ops);
 	if (ret) {
 		printf("error reading OOB block 0\n");
 		return ret;
 	}
 
 	if (oob_buf[0] == ENV_OOB_MARKER) {
-		*result = oob_buf[1] * nand->erasesize;
+		*result = oob_buf[1] * mtd->erasesize;
 	} else if (oob_buf[0] == ENV_OOB_MARKER_OLD) {
 		*result = oob_buf[1];
 	} else {
@@ -387,7 +387,7 @@
 	ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE);
 
 #if defined(CONFIG_ENV_OFFSET_OOB)
-	ret = get_nand_env_oob(&nand_info[0], &nand_env_oob_offset);
+	ret = get_nand_env_oob(nand_info[0], &nand_env_oob_offset);
 	/*
 	 * If unable to read environment offset from NAND OOB then fall through
 	 * to the normal environment reading code below
diff --git a/common/fb_nand.c b/common/fb_nand.c
index 9ca8602..e55ea38 100644
--- a/common/fb_nand.c
+++ b/common/fb_nand.c
@@ -19,7 +19,7 @@
 static char *response_str;
 
 struct fb_nand_sparse {
-	nand_info_t		*nand;
+	struct mtd_info		*nand;
 	struct part_info	*part;
 };
 
@@ -34,7 +34,7 @@
 }
 
 static int fb_nand_lookup(const char *partname, char *response,
-			  nand_info_t **nand,
+			  struct mtd_info **nand,
 			  struct part_info **part)
 {
 	struct mtd_device *dev;
@@ -62,12 +62,12 @@
 		return -EINVAL;
 	}
 
-	*nand = &nand_info[dev->id->num];
+	*mtd = nand_info[dev->id->num];
 
 	return 0;
 }
 
-static int _fb_nand_erase(nand_info_t *nand, struct part_info *part)
+static int _fb_nand_erase(struct mtd_info *mtd, struct part_info *part)
 {
 	nand_erase_options_t opts;
 	int ret;
@@ -80,7 +80,7 @@
 	printf("Erasing blocks 0x%llx to 0x%llx\n",
 	       part->offset, part->offset + part->size);
 
-	ret = nand_erase_opts(nand, &opts);
+	ret = nand_erase_opts(mtd, &opts);
 	if (ret)
 		return ret;
 
@@ -90,7 +90,7 @@
 	return 0;
 }
 
-static int _fb_nand_write(nand_info_t *nand, struct part_info *part,
+static int _fb_nand_write(struct mtd_info *mtd, struct part_info *part,
 			  void *buffer, unsigned int offset,
 			  unsigned int length, size_t *written)
 {
@@ -100,7 +100,7 @@
 	flags |= WITH_DROP_FFS;
 #endif
 
-	return nand_write_skip_bad(nand, offset, &length, written,
+	return nand_write_skip_bad(mtd, offset, &length, written,
 				   part->size - (offset - part->offset),
 				   buffer, flags);
 }
@@ -131,13 +131,13 @@
 			 char *response)
 {
 	struct part_info *part;
-	nand_info_t *nand = NULL;
+	struct mtd_info *mtd = NULL;
 	int ret;
 
 	/* initialize the response buffer */
 	response_str = response;
 
-	ret = fb_nand_lookup(partname, response, &nand, &part);
+	ret = fb_nand_lookup(partname, response, &mtd, &part);
 	if (ret) {
 		error("invalid NAND device");
 		fastboot_fail(response_str, "invalid NAND device");
@@ -152,10 +152,10 @@
 		struct fb_nand_sparse sparse_priv;
 		sparse_storage_t sparse;
 
-		sparse_priv.nand = nand;
+		sparse_priv.nand = mtd;
 		sparse_priv.part = part;
 
-		sparse.block_sz = nand->writesize;
+		sparse.block_sz = mtd->writesize;
 		sparse.start = part->offset / sparse.block_sz;
 		sparse.size = part->size  / sparse.block_sz;
 		sparse.name = part->name;
@@ -167,7 +167,7 @@
 		printf("Flashing raw image at offset 0x%llx\n",
 		       part->offset);
 
-		ret = _fb_nand_write(nand, part, download_buffer, part->offset,
+		ret = _fb_nand_write(mtd, part, download_buffer, part->offset,
 				     download_bytes, NULL);
 
 		printf("........ wrote %u bytes to '%s'\n",
@@ -185,13 +185,13 @@
 void fb_nand_erase(const char *partname, char *response)
 {
 	struct part_info *part;
-	nand_info_t *nand = NULL;
+	struct mtd_info *mtd = NULL;
 	int ret;
 
 	/* initialize the response buffer */
 	response_str = response;
 
-	ret = fb_nand_lookup(partname, response, &nand, &part);
+	ret = fb_nand_lookup(partname, response, &mtd, &part);
 	if (ret) {
 		error("invalid NAND device");
 		fastboot_fail(response_str, "invalid NAND device");
@@ -202,9 +202,9 @@
 	if (ret)
 		return;
 
-	ret = _fb_nand_erase(nand, part);
+	ret = _fb_nand_erase(mtd, part);
 	if (ret) {
-		error("failed erasing from device %s", nand->name);
+		error("failed erasing from device %s", mtd->name);
 		fastboot_fail(response_str, "failed erasing from device");
 		return;
 	}
diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c
index c9eb020..9874708 100644
--- a/common/spl/spl_fit.c
+++ b/common/spl/spl_fit.c
@@ -77,7 +77,7 @@
 	for (node = fdt_first_subnode(fdt, conf);
 	     node >= 0;
 	     node = fdt_next_subnode(fdt, node)) {
-		name = fdt_getprop(fdt, node, "name", &len);
+		name = fdt_getprop(fdt, node, "description", &len);
 		printf("   %s\n", name);
 	}
 #endif
diff --git a/common/splash_source.c b/common/splash_source.c
index a09dd4b..f86a78a 100644
--- a/common/splash_source.c
+++ b/common/splash_source.c
@@ -45,9 +45,9 @@
 #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,
+	return nand_read_skip_bad(nand_info[nand_curr_device], offset,
 				  &read_size, NULL,
-				  nand_info[nand_curr_device].size,
+				  nand_info[nand_curr_device]->size,
 				  (u_char *)bmp_load_addr);
 }
 #else
diff --git a/configs/ls1012afrdm_qspi_defconfig b/configs/ls1012afrdm_qspi_defconfig
new file mode 100644
index 0000000..04189de
--- /dev/null
+++ b/configs/ls1012afrdm_qspi_defconfig
@@ -0,0 +1,32 @@
+CONFIG_ARM=y
+CONFIG_TARGET_LS1012AFRDM=y
+# CONFIG_SYS_MALLOC_F is not set
+CONFIG_SPI_FLASH=y
+CONFIG_DM_SPI=y
+CONFIG_DM_SPI_FLASH=y
+CONFIG_DEFAULT_DEVICE_TREE="fsl-ls1012a-frdm"
+CONFIG_FIT=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_OF_BOARD_SETUP=y
+CONFIG_OF_STDOUT_VIA_ALIAS=y
+CONFIG_SYS_EXTRA_OPTIONS="QSPI_BOOT"
+CONFIG_HUSH_PARSER=y
+CONFIG_CMD_GREPENV=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_USB=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_FAT=y
+CONFIG_OF_CONTROL=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_DM=y
+CONFIG_NETDEVICES=y
+CONFIG_SYS_NS16550=y
+CONFIG_USB=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_XHCI_DWC3=y
diff --git a/configs/ls1012aqds_qspi_defconfig b/configs/ls1012aqds_qspi_defconfig
new file mode 100644
index 0000000..935f2fd
--- /dev/null
+++ b/configs/ls1012aqds_qspi_defconfig
@@ -0,0 +1,35 @@
+CONFIG_ARM=y
+CONFIG_TARGET_LS1012AQDS=y
+# CONFIG_SYS_MALLOC_F is not set
+CONFIG_SPI_FLASH=y
+CONFIG_DM_SPI=y
+CONFIG_DM_SPI_FLASH=y
+CONFIG_DEFAULT_DEVICE_TREE="fsl-ls1012a-qds"
+CONFIG_FIT=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_OF_BOARD_SETUP=y
+CONFIG_OF_STDOUT_VIA_ALIAS=y
+CONFIG_SYS_EXTRA_OPTIONS="QSPI_BOOT"
+CONFIG_HUSH_PARSER=y
+CONFIG_CMD_GREPENV=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_USB=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_FAT=y
+CONFIG_OF_CONTROL=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_DM=y
+CONFIG_NETDEVICES=y
+CONFIG_E1000=y
+CONFIG_SYS_NS16550=y
+CONFIG_FSL_DSPI=y
+CONFIG_USB=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_XHCI_DWC3=y
diff --git a/configs/ls1012ardb_qspi_defconfig b/configs/ls1012ardb_qspi_defconfig
new file mode 100644
index 0000000..5c28bd1
--- /dev/null
+++ b/configs/ls1012ardb_qspi_defconfig
@@ -0,0 +1,35 @@
+CONFIG_ARM=y
+CONFIG_TARGET_LS1012ARDB=y
+# CONFIG_SYS_MALLOC_F is not set
+CONFIG_SPI_FLASH=y
+CONFIG_DM_SPI=y
+CONFIG_DM_SPI_FLASH=y
+CONFIG_DEFAULT_DEVICE_TREE="fsl-ls1012a-rdb"
+CONFIG_FIT=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_OF_BOARD_SETUP=y
+CONFIG_OF_STDOUT_VIA_ALIAS=y
+CONFIG_SYS_EXTRA_OPTIONS="QSPI_BOOT"
+CONFIG_HUSH_PARSER=y
+CONFIG_CMD_GREPENV=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_USB=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_FAT=y
+CONFIG_OF_CONTROL=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_DM=y
+CONFIG_NETDEVICES=y
+CONFIG_E1000=y
+CONFIG_SYS_NS16550=y
+CONFIG_FSL_DSPI=y
+CONFIG_USB=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_XHCI_DWC3=y
diff --git a/configs/microblaze-generic_defconfig b/configs/microblaze-generic_defconfig
index 8c7e4b7..2ef713f 100644
--- a/configs/microblaze-generic_defconfig
+++ b/configs/microblaze-generic_defconfig
@@ -2,6 +2,10 @@
 CONFIG_SPL_SYS_MALLOC_SIMPLE=y
 CONFIG_SPL_DM=y
 CONFIG_TARGET_MICROBLAZE_GENERIC=y
+CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR=1
+CONFIG_XILINX_MICROBLAZE0_USE_BARREL=1
+CONFIG_XILINX_MICROBLAZE0_USE_DIV=1
+CONFIG_XILINX_MICROBLAZE0_USE_HW_MUL=1
 CONFIG_SYS_TEXT_BASE=0x29000000
 CONFIG_DEFAULT_DEVICE_TREE="microblaze-generic"
 CONFIG_SPL=y
diff --git a/configs/p2771-0000_defconfig b/configs/p2771-0000_defconfig
new file mode 100644
index 0000000..9f2c418
--- /dev/null
+++ b/configs/p2771-0000_defconfig
@@ -0,0 +1,31 @@
+CONFIG_ARM=y
+CONFIG_TEGRA=y
+CONFIG_TEGRA186=y
+CONFIG_TARGET_P2771_0000=y
+CONFIG_DEFAULT_DEVICE_TREE="tegra186-p2771-0000"
+CONFIG_OF_SYSTEM_SETUP=y
+CONFIG_HUSH_PARSER=y
+CONFIG_SYS_PROMPT="Tegra186 (P2771-0000) # "
+# CONFIG_CMD_IMI is not set
+# CONFIG_CMD_IMLS is not set
+# CONFIG_CMD_FLASH is not set
+CONFIG_CMD_MMC=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_GPIO=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_DHCP=y
+# CONFIG_CMD_NFS is not set
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_EXT4_WRITE=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_SYS_NS16550=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
diff --git a/configs/xilinx_zynqmp_ep_defconfig b/configs/xilinx_zynqmp_ep_defconfig
index ad94d56..fa380ef 100644
--- a/configs/xilinx_zynqmp_ep_defconfig
+++ b/configs/xilinx_zynqmp_ep_defconfig
@@ -1,7 +1,7 @@
 CONFIG_ARM=y
 CONFIG_SYS_CONFIG_NAME="xilinx_zynqmp_ep"
 CONFIG_ARCH_ZYNQMP=y
-CONFIG_SYS_MALLOC_F_LEN=0x4000
+CONFIG_SYS_MALLOC_F_LEN=0x8000
 CONFIG_DM_I2C=y
 CONFIG_DM_GPIO=y
 CONFIG_ZYNQMP_USB=y
@@ -9,6 +9,7 @@
 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-ep108"
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
+CONFIG_SPL_LOAD_FIT=y
 CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="ZynqMP> "
 # CONFIG_CMD_CONSOLE is not set
@@ -19,6 +20,7 @@
 # CONFIG_CMD_LOADB is not set
 # CONFIG_CMD_LOADS is not set
 CONFIG_CMD_MMC=y
+CONFIG_CMD_NAND=y
 CONFIG_CMD_I2C=y
 CONFIG_CMD_USB=y
 CONFIG_CMD_DFU=y
diff --git a/configs/xilinx_zynqmp_zc1751_xm015_dc1_defconfig b/configs/xilinx_zynqmp_zc1751_xm015_dc1_defconfig
index ad1566d..35226d6 100644
--- a/configs/xilinx_zynqmp_zc1751_xm015_dc1_defconfig
+++ b/configs/xilinx_zynqmp_zc1751_xm015_dc1_defconfig
@@ -1,6 +1,7 @@
 CONFIG_ARM=y
 CONFIG_SYS_CONFIG_NAME="xilinx_zynqmp_zc1751_xm015_dc1"
 CONFIG_ARCH_ZYNQMP=y
+CONFIG_SYS_MALLOC_F_LEN=0x8000
 CONFIG_DM_I2C=y
 CONFIG_DM_GPIO=y
 CONFIG_ZYNQMP_USB=y
@@ -8,6 +9,7 @@
 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zc1751-xm015-dc1"
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
+CONFIG_SPL_LOAD_FIT=y
 CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="ZynqMP> "
 # CONFIG_CMD_IMLS is not set
diff --git a/configs/xilinx_zynqmp_zc1751_xm016_dc2_defconfig b/configs/xilinx_zynqmp_zc1751_xm016_dc2_defconfig
index 3aa80cb..cc13179 100644
--- a/configs/xilinx_zynqmp_zc1751_xm016_dc2_defconfig
+++ b/configs/xilinx_zynqmp_zc1751_xm016_dc2_defconfig
@@ -1,6 +1,7 @@
 CONFIG_ARM=y
 CONFIG_SYS_CONFIG_NAME="xilinx_zynqmp_zc1751_xm016_dc2"
 CONFIG_ARCH_ZYNQMP=y
+CONFIG_SYS_MALLOC_F_LEN=0x8000
 CONFIG_DM_I2C=y
 CONFIG_DM_GPIO=y
 CONFIG_ZYNQMP_USB=y
@@ -8,11 +9,13 @@
 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zc1751-xm016-dc2"
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
+CONFIG_SPL_LOAD_FIT=y
 CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="ZynqMP> "
 # CONFIG_CMD_IMLS is not set
 CONFIG_CMD_MEMTEST=y
 # CONFIG_CMD_FLASH is not set
+CONFIG_CMD_NAND=y
 CONFIG_CMD_I2C=y
 CONFIG_CMD_USB=y
 CONFIG_CMD_DFU=y
@@ -40,6 +43,11 @@
 CONFIG_SPI_FLASH_SST=y
 CONFIG_DM_ETH=y
 CONFIG_ZYNQ_GEM=y
+CONFIG_DEBUG_UART=y
+CONFIG_DEBUG_UART_ZYNQ=y
+CONFIG_DEBUG_UART_BASE=0xff000000
+CONFIG_DEBUG_UART_CLOCK=100000000
+CONFIG_DEBUG_UART_ANNOUNCE=y
 CONFIG_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
diff --git a/configs/xilinx_zynqmp_zc1751_xm018_dc4_defconfig b/configs/xilinx_zynqmp_zc1751_xm018_dc4_defconfig
new file mode 100644
index 0000000..6570348
--- /dev/null
+++ b/configs/xilinx_zynqmp_zc1751_xm018_dc4_defconfig
@@ -0,0 +1,43 @@
+CONFIG_ARM=y
+CONFIG_SYS_CONFIG_NAME="xilinx_zynqmp_zc1751_xm018_dc4"
+CONFIG_ARCH_ZYNQMP=y
+CONFIG_SYS_MALLOC_F_LEN=0x8000
+CONFIG_DM_I2C=y
+CONFIG_DM_GPIO=y
+CONFIG_SYS_TEXT_BASE=0x8000000
+CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zc1751-xm018-dc4"
+CONFIG_FIT=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_SPL_LOAD_FIT=y
+CONFIG_HUSH_PARSER=y
+CONFIG_SYS_PROMPT="ZynqMP> "
+# CONFIG_CMD_IMLS is not set
+CONFIG_CMD_MEMTEST=y
+# CONFIG_CMD_FLASH is not set
+CONFIG_CMD_MMC=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_TFTPPUT=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_TIME=y
+CONFIG_CMD_TIMER=y
+CONFIG_CMD_EXT2=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_EXT4_WRITE=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_OF_EMBED=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_CLK=y
+CONFIG_SPL_CLK=y
+CONFIG_SYS_I2C_CADENCE=y
+CONFIG_DM_MMC=y
+CONFIG_ZYNQ_SDHCI=y
+CONFIG_DM_ETH=y
+CONFIG_ZYNQ_GEM=y
+CONFIG_DEBUG_UART=y
+CONFIG_DEBUG_UART_ZYNQ=y
+CONFIG_DEBUG_UART_BASE=0xff000000
+CONFIG_DEBUG_UART_CLOCK=100000000
+CONFIG_DEBUG_UART_ANNOUNCE=y
diff --git a/configs/xilinx_zynqmp_zc1751_xm019_dc5_defconfig b/configs/xilinx_zynqmp_zc1751_xm019_dc5_defconfig
index f7c671b..e1fc8b0 100644
--- a/configs/xilinx_zynqmp_zc1751_xm019_dc5_defconfig
+++ b/configs/xilinx_zynqmp_zc1751_xm019_dc5_defconfig
@@ -1,12 +1,14 @@
 CONFIG_ARM=y
 CONFIG_SYS_CONFIG_NAME="xilinx_zynqmp_zc1751_xm019_dc5"
 CONFIG_ARCH_ZYNQMP=y
+CONFIG_SYS_MALLOC_F_LEN=0x8000
 CONFIG_DM_I2C=y
 CONFIG_DM_GPIO=y
 CONFIG_SYS_TEXT_BASE=0x8000000
 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zc1751-xm019-dc5"
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
+CONFIG_SPL_LOAD_FIT=y
 CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="ZynqMP> "
 # CONFIG_CMD_IMLS is not set
diff --git a/configs/xilinx_zynqmp_zcu102_defconfig b/configs/xilinx_zynqmp_zcu102_defconfig
index a216f11..2829029 100644
--- a/configs/xilinx_zynqmp_zcu102_defconfig
+++ b/configs/xilinx_zynqmp_zcu102_defconfig
@@ -1,12 +1,14 @@
 CONFIG_ARM=y
 CONFIG_SYS_CONFIG_NAME="xilinx_zynqmp_zcu102"
 CONFIG_ARCH_ZYNQMP=y
+CONFIG_SYS_MALLOC_F_LEN=0x8000
 CONFIG_DM_GPIO=y
 CONFIG_ZYNQMP_USB=y
 CONFIG_SYS_TEXT_BASE=0x8000000
 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zcu102"
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
+CONFIG_SPL_LOAD_FIT=y
 CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="ZynqMP> "
 # CONFIG_CMD_IMLS is not set
diff --git a/configs/xilinx_zynqmp_zcu102_revB_defconfig b/configs/xilinx_zynqmp_zcu102_revB_defconfig
index 514176d..92633d6 100644
--- a/configs/xilinx_zynqmp_zcu102_revB_defconfig
+++ b/configs/xilinx_zynqmp_zcu102_revB_defconfig
@@ -1,12 +1,14 @@
 CONFIG_ARM=y
 CONFIG_SYS_CONFIG_NAME="xilinx_zynqmp_zcu102"
 CONFIG_ARCH_ZYNQMP=y
+CONFIG_SYS_MALLOC_F_LEN=0x8000
 CONFIG_DM_GPIO=y
 CONFIG_ZYNQMP_USB=y
 CONFIG_SYS_TEXT_BASE=0x8000000
 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zcu102-revB"
 CONFIG_FIT=y
 CONFIG_FIT_VERBOSE=y
+CONFIG_SPL_LOAD_FIT=y
 CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="ZynqMP> "
 # CONFIG_CMD_IMLS is not set
diff --git a/doc/README.nand b/doc/README.nand
index 545d88c..96ffc48 100644
--- a/doc/README.nand
+++ b/doc/README.nand
@@ -136,15 +136,8 @@
       Example of new init to be added to the end of an existing driver
       init:
 
-	/*
-	 * devnum is the device number to be used in nand commands
-	 * and in mtd->name.  Must be less than
-	 * CONFIG_SYS_NAND_MAX_DEVICE.
-	 */
-	mtd = &nand_info[devnum];
-
 	/* chip is struct nand_chip, and is now provided by the driver. */
-	mtd->priv = &chip;
+	mtd = &chip.mtd;
 
 	/*
 	 * Fill in appropriate values if this driver uses these fields,
@@ -165,7 +158,11 @@
 	if (nand_scan_tail(mtd))
 		error out
 
-	if (nand_register(devnum))
+	/*
+	 * devnum is the device number to be used in nand commands
+	 * and in mtd->name.  Must be less than CONFIG_SYS_NAND_MAX_DEVICE.
+	 */
+	if (nand_register(devnum, mtd))
 		error out
 
       In addition to providing more flexibility to the driver, it reduces
diff --git a/doc/device-tree-bindings/gpio/nvidia,tegra186-gpio.txt b/doc/device-tree-bindings/gpio/nvidia,tegra186-gpio.txt
new file mode 100644
index 0000000..c82a2e2
--- /dev/null
+++ b/doc/device-tree-bindings/gpio/nvidia,tegra186-gpio.txt
@@ -0,0 +1,161 @@
+NVIDIA Tegra186 GPIO controllers
+
+Tegra186 contains two GPIO controllers; a main controller and an "AON"
+controller. This binding document applies to both controllers. The register
+layouts for the controllers share many similarities, but also some significant
+differences. Hence, this document describes closely related but different
+bindings and compatible values.
+
+The Tegra186 GPIO controller allows software to set the IO direction of, and
+read/write the value of, numerous GPIO signals. Routing of GPIO signals to
+package balls is under the control of a separate pin controller HW block. Two
+major sets of registers exist:
+
+a) Security registers, which allow configuration of allowed access to the GPIO
+register set. These registers exist in a single contiguous block of physical
+address space. The size of this block, and the security features available,
+varies between the different GPIO controllers.
+
+Access to this set of registers is not necessary in all circumstances. Code
+that wishes to configure access to the GPIO registers needs access to these
+registers to do so. Code which simply wishes to read or write GPIO data does not
+need access to these registers.
+
+b) GPIO registers, which allow manipulation of the GPIO signals. In some GPIO
+controllers, these registers are exposed via multiple "physical aliases" in
+address space, each of which access the same underlying state. See the hardware
+documentation for rationale. Any particular GPIO client is expected to access
+just one of these physical aliases.
+
+Tegra HW documentation describes a unified naming convention for all GPIOs
+implemented by the SoC. Each GPIO is assigned to a port, and a port may control
+a number of GPIOs. Thus, each GPIO is named according to an alphabetical port
+name and an integer GPIO name within the port. For example, GPIO_PA0, GPIO_PN6,
+or GPIO_PCC3.
+
+The number of ports implemented by each GPIO controller varies. The number of
+implemented GPIOs within each port varies. GPIO registers within a controller
+are grouped and laid out according to the port they affect.
+
+The mapping from port name to the GPIO controller that implements that port, and
+the mapping from port name to register offset within a controller, are both
+extremely non-linear. The header file <dt-bindings/gpio/tegra186-gpio.h>
+describes the port-level mapping. In that file, the naming convention for ports
+matches the HW documentation. The values chosen for the names are alphabetically
+sorted within a particular controller. Drivers need to map between the DT GPIO
+IDs and HW register offsets using a lookup table.
+
+Each GPIO controller can generate a number of interrupt signals. Each signal
+represents the aggregate status for all GPIOs within a set of ports. Thus, the
+number of interrupt signals generated by a controller varies as a rough function
+of the number of ports it implements. Note that the HW documentation refers to
+both the overall controller HW module and the sets-of-ports as "controllers".
+
+Each GPIO controller in fact generates multiple interrupts signals for each set
+of ports. Each GPIO may be configured to feed into a specific one of the
+interrupt signals generated by a set-of-ports. The intent is for each generated
+signal to be routed to a different CPU, thus allowing different CPUs to each
+handle subsets of the interrupts within a port. The status of each of these
+per-port-set signals is reported via a separate register. Thus, a driver needs
+to know which status register to observe. This binding currently defines no
+configuration mechanism for this. By default, drivers should use register
+GPIO_${port}_INTERRUPT_STATUS_G1_0. Future revisions to the binding could
+define a property to configure this.
+
+Required properties:
+- compatible
+    Array of strings.
+    One of:
+    - "nvidia,tegra186-gpio".
+    - "nvidia,tegra186-gpio-aon".
+- reg-names
+    Array of strings.
+    Contains a list of names for the register spaces described by the reg
+    property. May contain the following entries, in any order:
+    - "gpio": Mandatory. GPIO control registers. This may cover either:
+        a) The single physical alias that this OS should use.
+        b) All physical aliases that exist in the controller. This is
+           appropriate when the OS is responsible for managing assignment of
+           the physical aliases.
+    - "security": Optional. Security configuration registers.
+    Users of this binding MUST look up entries in the reg property by name,
+    using this reg-names property to do so.
+- reg
+    Array of (physical base address, length) tuples.
+    Must contain one entry per entry in the reg-names property, in a matching
+    order.
+- interrupts
+    Array of interrupt specifiers.
+    The interrupt outputs from the HW block, one per set of ports, in the
+    order the HW manual describes them. The number of entries required varies
+    depending on compatible value:
+    - "nvidia,tegra186-gpio": 6 entries.
+    - "nvidia,tegra186-gpio-aon": 1 entry.
+- gpio-controller
+    Boolean.
+    Marks the device node as a GPIO controller/provider.
+- #gpio-cells
+    Single-cell integer.
+    Must be <2>.
+    Indicates how many cells are used in a consumer's GPIO specifier.
+    In the specifier:
+    - The first cell is the pin number.
+        See <dt-bindings/gpio/tegra186-gpio.h>.
+    - The second cell contains flags:
+        - Bit 0 specifies polarity
+            - 0: Active-high (normal).
+            - 1: Active-low (inverted).
+- interrupt-controller
+    Boolean.
+    Marks the device node as an interrupt controller/provider.
+- #interrupt-cells
+    Single-cell integer.
+    Must be <2>.
+    Indicates how many cells are used in a consumer's interrupt specifier.
+    In the specifier:
+    - The first cell is the GPIO number.
+        See <dt-bindings/gpio/tegra186-gpio.h>.
+    - The second cell is contains flags:
+        - Bits [3:0] indicate trigger type and level:
+            - 1: Low-to-high edge triggered.
+            - 2: High-to-low edge triggered.
+            - 4: Active high level-sensitive.
+            - 8: Active low level-sensitive.
+            Valid combinations are 1, 2, 3, 4, 8.
+
+Example:
+
+#include <dt-bindings/interrupt-controller/irq.h>
+
+gpio@2200000 {
+	compatible = "nvidia,tegra186-gpio";
+	reg-names = "security", "gpio";
+	reg =
+		<0x0 0x2200000 0x0 0x10000>,
+		<0x0 0x2210000 0x0 0x10000>;
+	interrupts =
+		<0 47 IRQ_TYPE_LEVEL_HIGH>,
+		<0 50 IRQ_TYPE_LEVEL_HIGH>,
+		<0 53 IRQ_TYPE_LEVEL_HIGH>,
+		<0 56 IRQ_TYPE_LEVEL_HIGH>,
+		<0 59 IRQ_TYPE_LEVEL_HIGH>,
+		<0 180 IRQ_TYPE_LEVEL_HIGH>;
+	gpio-controller;
+	#gpio-cells = <2>;
+	interrupt-controller;
+	#interrupt-cells = <2>;
+};
+
+gpio@c2f0000 {
+	compatible = "nvidia,tegra186-gpio-aon";
+	reg-names = "security", "gpio";
+	reg =
+		<0x0 0xc2f0000 0x0 0x1000>,
+		<0x0 0xc2f1000 0x0 0x1000>;
+	interrupts =
+		<0 60 IRQ_TYPE_LEVEL_HIGH>;
+	gpio-controller;
+	#gpio-cells = <2>;
+	interrupt-controller;
+	#interrupt-cells = <2>;
+};
diff --git a/drivers/ddr/fsl/ctrl_regs.c b/drivers/ddr/fsl/ctrl_regs.c
index 9073917..1d5cec6 100644
--- a/drivers/ddr/fsl/ctrl_regs.c
+++ b/drivers/ddr/fsl/ctrl_regs.c
@@ -709,7 +709,7 @@
 		| ((add_lat_mclk & 0xf) << 28)
 		| ((cpo & 0x1f) << 23)
 		| ((wr_lat & 0xf) << 19)
-		| ((wr_lat & 0x10) << 14)
+		| ((wr_lat & 0x10) << 18)
 		| ((rd_to_pre & RD_TO_PRE_MASK) << RD_TO_PRE_SHIFT)
 		| ((wr_data_delay & WR_DATA_DELAY_MASK) << WR_DATA_DELAY_SHIFT)
 		| ((cke_pls & 0x7) << 6)
@@ -1835,10 +1835,17 @@
 	/* Per FSL Application Note: AN2805 */
 	ss_en = 1;
 #endif
-	clk_adjust = popts->clk_adjust;
+	if (fsl_ddr_get_version(0) >= 0x40701) {
+		/* clk_adjust in 5-bits on T-series and LS-series */
+		clk_adjust = (popts->clk_adjust & 0x1F) << 22;
+	} else {
+		/* clk_adjust in 4-bits on earlier MPC85xx and P-series */
+		clk_adjust = (popts->clk_adjust & 0xF) << 23;
+	}
+
 	ddr->ddr_sdram_clk_cntl = (0
 				   | ((ss_en & 0x1) << 31)
-				   | ((clk_adjust & 0xF) << 23)
+				   | clk_adjust
 				   );
 	debug("FSLDDR: clk_cntl = 0x%08x\n", ddr->ddr_sdram_clk_cntl);
 }
diff --git a/drivers/ddr/fsl/fsl_ddr_gen4.c b/drivers/ddr/fsl/fsl_ddr_gen4.c
index 5039f5d..d37e247 100644
--- a/drivers/ddr/fsl/fsl_ddr_gen4.c
+++ b/drivers/ddr/fsl/fsl_ddr_gen4.c
@@ -206,12 +206,14 @@
 
 #ifdef CONFIG_SYS_FSL_ERRATUM_A009803
 	/* part 1 of 2 */
-	if (regs->ddr_sdram_cfg & SDRAM_CFG_RD_EN) { /* for RDIMM */
-		ddr_out32(&ddr->ddr_sdram_rcw_2,
-			  regs->ddr_sdram_rcw_2 & ~0x0f000000);
+	if (regs->ddr_sdram_cfg_2 & SDRAM_CFG2_AP_EN) {
+		if (regs->ddr_sdram_cfg & SDRAM_CFG_RD_EN) { /* for RDIMM */
+			ddr_out32(&ddr->ddr_sdram_rcw_2,
+				  regs->ddr_sdram_rcw_2 & ~0x0f000000);
+		}
+		ddr_out32(&ddr->err_disable, regs->err_disable |
+			  DDR_ERR_DISABLE_APED);
 	}
-
-	ddr_out32(&ddr->err_disable, regs->err_disable | DDR_ERR_DISABLE_APED);
 #else
 	ddr_out32(&ddr->err_disable, regs->err_disable);
 #endif
@@ -395,22 +397,24 @@
 #endif /* CONFIG_SYS_FSL_ERRATUM_A008511 */
 
 #ifdef CONFIG_SYS_FSL_ERRATUM_A009803
-		/* if it's RDIMM */
-		if (regs->ddr_sdram_cfg & SDRAM_CFG_RD_EN) {
-			for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
-				if (!(regs->cs[i].config & SDRAM_CS_CONFIG_EN))
-					continue;
-				set_wait_for_bits_clear(&ddr->sdram_md_cntl,
-							MD_CNTL_MD_EN |
-							MD_CNTL_CS_SEL(i) |
-							0x070000ed,
-							MD_CNTL_MD_EN);
-				udelay(1);
+		if (regs->ddr_sdram_cfg_2 & SDRAM_CFG2_AP_EN) {
+			/* if it's RDIMM */
+			if (regs->ddr_sdram_cfg & SDRAM_CFG_RD_EN) {
+				for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+					if (!(regs->cs[i].config & SDRAM_CS_CONFIG_EN))
+						continue;
+					set_wait_for_bits_clear(&ddr->sdram_md_cntl,
+								MD_CNTL_MD_EN |
+								MD_CNTL_CS_SEL(i) |
+								0x070000ed,
+								MD_CNTL_MD_EN);
+					udelay(1);
+				}
 			}
-		}
 
-		ddr_out32(&ddr->err_disable,
-			  regs->err_disable & ~DDR_ERR_DISABLE_APED);
+			ddr_out32(&ddr->err_disable,
+				  regs->err_disable & ~DDR_ERR_DISABLE_APED);
+		}
 #endif
 	}
 #endif
diff --git a/drivers/ddr/fsl/options.c b/drivers/ddr/fsl/options.c
index d0075ff..793d12a 100644
--- a/drivers/ddr/fsl/options.c
+++ b/drivers/ddr/fsl/options.c
@@ -886,7 +886,8 @@
 	} else
 		popts->ecc_mode = 1;
 #endif
-	popts->ecc_init_using_memctl = 1; /* 0 = use DMA, 1 = use memctl */
+	/* 1 = use memory controler to init data */
+	popts->ecc_init_using_memctl = popts->ecc_mode ? 1 : 0;
 
 	/*
 	 * Choose DQS config
diff --git a/drivers/dfu/dfu_nand.c b/drivers/dfu/dfu_nand.c
index a975492..ab782be 100644
--- a/drivers/dfu/dfu_nand.c
+++ b/drivers/dfu/dfu_nand.c
@@ -25,7 +25,7 @@
 	loff_t start, lim;
 	size_t count, actual;
 	int ret;
-	nand_info_t *nand;
+	struct mtd_info *mtd;
 
 	/* if buf == NULL return total size of the area */
 	if (buf == NULL) {
@@ -39,16 +39,16 @@
 
 	if (nand_curr_device < 0 ||
 	    nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE ||
-	    !nand_info[nand_curr_device].name) {
+	    !nand_info[nand_curr_device]->name) {
 		printf("%s: invalid nand device\n", __func__);
 		return -1;
 	}
 
-	nand = &nand_info[nand_curr_device];
+	mtd = nand_info[nand_curr_device];
 
 	if (op == DFU_OP_READ) {
-		ret = nand_read_skip_bad(nand, start, &count, &actual,
-				lim, buf);
+		ret = nand_read_skip_bad(mtd, start, &count, &actual,
+					 lim, buf);
 	} else {
 		nand_erase_options_t opts;
 
@@ -59,12 +59,12 @@
 		opts.quiet = 1;
 		opts.lim = lim;
 		/* first erase */
-		ret = nand_erase_opts(nand, &opts);
+		ret = nand_erase_opts(mtd, &opts);
 		if (ret)
 			return ret;
 		/* then write */
-		ret = nand_write_skip_bad(nand, start, &count, &actual,
-				lim, buf, WITH_WR_VERIFY);
+		ret = nand_write_skip_bad(mtd, start, &count, &actual,
+					  lim, buf, WITH_WR_VERIFY);
 	}
 
 	if (ret != 0) {
@@ -142,24 +142,24 @@
 
 	/* in case of ubi partition, erase rest of the partition */
 	if (dfu->data.nand.ubi) {
-		nand_info_t *nand;
+		struct mtd_info *mtd;
 		nand_erase_options_t opts;
 
 		if (nand_curr_device < 0 ||
 		    nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE ||
-		    !nand_info[nand_curr_device].name) {
+		    !nand_info[nand_curr_device]->name) {
 			printf("%s: invalid nand device\n", __func__);
 			return -1;
 		}
 
-		nand = &nand_info[nand_curr_device];
+		mtd = nand_info[nand_curr_device];
 
 		memset(&opts, 0, sizeof(opts));
 		opts.offset = dfu->data.nand.start + dfu->offset +
 				dfu->bad_skip;
 		opts.length = dfu->data.nand.start +
 				dfu->data.nand.size - opts.offset;
-		ret = nand_erase_opts(nand, &opts);
+		ret = nand_erase_opts(mtd, &opts);
 		if (ret != 0)
 			printf("Failure erase: %d\n", ret);
 	}
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 93a7e8c..73b862d 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -109,6 +109,21 @@
 	  of 'anonymous' GPIOs that do not belong to any device or bank.
 	  Select a suitable value depending on your needs.
 
+config TEGRA_GPIO
+	bool "Tegra20..210 GPIO driver"
+	depends on DM_GPIO
+	help
+	  Support for the GPIO controller contained in NVIDIA Tegra20 through
+	  Tegra210.
+
+config TEGRA186_GPIO
+	bool "Tegra186 GPIO driver"
+	depends on DM_GPIO
+	help
+	  Support for the GPIO controller contained in NVIDIA Tegra186. This
+	  covers both the "main" and "AON" controller instances, even though
+	  they have slightly different register layout.
+
 config GPIO_UNIPHIER
 	bool "UniPhier GPIO"
 	depends on ARCH_UNIPHIER
@@ -173,4 +188,30 @@
 
 	  Now, max 24 bits chips and PCA953X compatible chips are
 	  supported
+
+config MPC85XX_GPIO
+	bool "Freescale MPC85XX GPIO driver"
+	depends on DM_GPIO
+	help
+	  This driver supports the built-in GPIO controller of MPC85XX CPUs.
+	  Each GPIO bank is identified by its own entry in the device tree,
+	  i.e.
+
+	  gpio-controller@fc00 {
+		#gpio-cells = <2>;
+		compatible = "fsl,pq3-gpio";
+		reg = <0xfc00 0x100>
+	  }
+
+	  By default, each bank is assumed to have 32 GPIOs, but the ngpios
+	  setting is honored, so the number of GPIOs for each bank is
+	  configurable to match the actual GPIO count of the SoC (e.g. the
+	  32/32/23 banks of the P1022 SoC).
+
+	  Aside from the standard functions of input/output mode, and output
+	  value setting, the open-drain feature, which can configure individual
+	  GPIOs to work as open-drain outputs, is supported.
+
+	  The driver has been tested on MPC85XX, but it is likely that other
+	  PowerQUICC III devices will work as well.
 endmenu
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index ddec1ef..792d191 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -31,10 +31,12 @@
 obj-$(CONFIG_SANDBOX_GPIO)	+= sandbox.o
 obj-$(CONFIG_SPEAR_GPIO)	+= spear_gpio.o
 obj-$(CONFIG_TEGRA_GPIO)	+= tegra_gpio.o
+obj-$(CONFIG_TEGRA186_GPIO)	+= tegra186_gpio.o
 obj-$(CONFIG_DA8XX_GPIO)	+= da8xx_gpio.o
 obj-$(CONFIG_DM644X_GPIO)	+= da8xx_gpio.o
 obj-$(CONFIG_ALTERA_PIO)	+= altera_pio.o
 obj-$(CONFIG_MPC83XX_GPIO)	+= mpc83xx_gpio.o
+obj-$(CONFIG_MPC85XX_GPIO)	+= mpc85xx_gpio.o
 obj-$(CONFIG_SH_GPIO_PFC)	+= sh_pfc.o
 obj-$(CONFIG_OMAP_GPIO)	+= omap_gpio.o
 obj-$(CONFIG_DB8500_GPIO)	+= db8500_gpio.o
diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
index 732b6c2..4559739 100644
--- a/drivers/gpio/gpio-uclass.c
+++ b/drivers/gpio/gpio-uclass.c
@@ -367,6 +367,38 @@
 	return 0;
 }
 
+int dm_gpio_get_open_drain(struct gpio_desc *desc)
+{
+	struct dm_gpio_ops *ops = gpio_get_ops(desc->dev);
+	int ret;
+
+	ret = check_reserved(desc, "get_open_drain");
+	if (ret)
+		return ret;
+
+	if (ops->set_open_drain)
+		return ops->get_open_drain(desc->dev, desc->offset);
+	else
+		return -ENOSYS;
+}
+
+int dm_gpio_set_open_drain(struct gpio_desc *desc, int value)
+{
+	struct dm_gpio_ops *ops = gpio_get_ops(desc->dev);
+	int ret;
+
+	ret = check_reserved(desc, "set_open_drain");
+	if (ret)
+		return ret;
+
+	if (ops->set_open_drain)
+		ret = ops->set_open_drain(desc->dev, desc->offset, value);
+	else
+		return 0; /* feature not supported -> ignore setting */
+
+	return ret;
+}
+
 int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags)
 {
 	struct udevice *dev = desc->dev;
diff --git a/drivers/gpio/mpc85xx_gpio.c b/drivers/gpio/mpc85xx_gpio.c
new file mode 100644
index 0000000..04773e2
--- /dev/null
+++ b/drivers/gpio/mpc85xx_gpio.c
@@ -0,0 +1,228 @@
+/*
+ * (C) Copyright 2016
+ * Mario Six, Guntermann & Drunck GmbH, six@gdsys.de
+ *
+ * based on arch/powerpc/include/asm/mpc85xx_gpio.h, which is
+ *
+ * Copyright 2010 eXMeritus, A Boeing Company
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <asm/gpio.h>
+#include <mapmem.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct ccsr_gpio {
+	u32	gpdir;
+	u32	gpodr;
+	u32	gpdat;
+	u32	gpier;
+	u32	gpimr;
+	u32	gpicr;
+};
+
+struct mpc85xx_gpio_data {
+	/* The bank's register base in memory */
+	struct ccsr_gpio __iomem *base;
+	/* The address of the registers; used to identify the bank */
+	ulong addr;
+	/* The GPIO count of the bank */
+	uint gpio_count;
+	/* The GPDAT register cannot be used to determine the value of output
+	 * pins on MPC8572/MPC8536, so we shadow it and use the shadowed value
+	 * for output pins */
+	u32 dat_shadow;
+};
+
+inline u32 gpio_mask(unsigned gpio) {
+	return (1U << (31 - (gpio)));
+}
+
+static inline u32 mpc85xx_gpio_get_val(struct ccsr_gpio *base, u32 mask)
+{
+	return in_be32(&base->gpdat) & mask;
+}
+
+static inline u32 mpc85xx_gpio_get_dir(struct ccsr_gpio *base, u32 mask)
+{
+	return in_be32(&base->gpdir) & mask;
+}
+
+static inline void mpc85xx_gpio_set_in(struct ccsr_gpio *base, u32 gpios)
+{
+	clrbits_be32(&base->gpdat, gpios);
+	/* GPDIR register 0 -> input */
+	clrbits_be32(&base->gpdir, gpios);
+}
+
+static inline void mpc85xx_gpio_set_low(struct ccsr_gpio *base, u32 gpios)
+{
+	clrbits_be32(&base->gpdat, gpios);
+	/* GPDIR register 1 -> output */
+	setbits_be32(&base->gpdir, gpios);
+}
+
+static inline void mpc85xx_gpio_set_high(struct ccsr_gpio *base, u32 gpios)
+{
+	setbits_be32(&base->gpdat, gpios);
+	/* GPDIR register 1 -> output */
+	setbits_be32(&base->gpdir, gpios);
+}
+
+static inline int mpc85xx_gpio_open_drain_val(struct ccsr_gpio *base, u32 mask)
+{
+	return in_be32(&base->gpodr) & mask;
+}
+
+static inline void mpc85xx_gpio_open_drain_on(struct ccsr_gpio *base, u32
+					      gpios)
+{
+	/* GPODR register 1 -> open drain on */
+	setbits_be32(&base->gpodr, gpios);
+}
+
+static inline void mpc85xx_gpio_open_drain_off(struct ccsr_gpio *base,
+					       u32 gpios)
+{
+	/* GPODR register 0 -> open drain off (actively driven) */
+	clrbits_be32(&base->gpodr, gpios);
+}
+
+static int mpc85xx_gpio_direction_input(struct udevice *dev, unsigned gpio)
+{
+	struct mpc85xx_gpio_data *data = dev_get_priv(dev);
+
+	mpc85xx_gpio_set_in(data->base, gpio_mask(gpio));
+	return 0;
+}
+
+static int mpc85xx_gpio_set_value(struct udevice *dev, unsigned gpio,
+				  int value)
+{
+	struct mpc85xx_gpio_data *data = dev_get_priv(dev);
+
+	if (value) {
+		data->dat_shadow |= gpio_mask(gpio);
+		mpc85xx_gpio_set_high(data->base, gpio_mask(gpio));
+	} else {
+		data->dat_shadow &= ~gpio_mask(gpio);
+		mpc85xx_gpio_set_low(data->base, gpio_mask(gpio));
+	}
+	return 0;
+}
+
+static int mpc85xx_gpio_direction_output(struct udevice *dev, unsigned gpio,
+					 int value)
+{
+	return mpc85xx_gpio_set_value(dev, gpio, value);
+}
+
+static int mpc85xx_gpio_get_value(struct udevice *dev, unsigned gpio)
+{
+	struct mpc85xx_gpio_data *data = dev_get_priv(dev);
+
+	if (!!mpc85xx_gpio_get_dir(data->base, gpio_mask(gpio))) {
+		/* Output -> use shadowed value */
+		return !!(data->dat_shadow & gpio_mask(gpio));
+	} else {
+		/* Input -> read value from GPDAT register */
+		return !!mpc85xx_gpio_get_val(data->base, gpio_mask(gpio));
+	}
+}
+
+static int mpc85xx_gpio_get_open_drain(struct udevice *dev, unsigned gpio)
+{
+	struct mpc85xx_gpio_data *data = dev_get_priv(dev);
+
+	return !!mpc85xx_gpio_open_drain_val(data->base, gpio_mask(gpio));
+}
+
+static int mpc85xx_gpio_set_open_drain(struct udevice *dev, unsigned gpio,
+				       int value)
+{
+	struct mpc85xx_gpio_data *data = dev_get_priv(dev);
+
+	if (value) {
+		mpc85xx_gpio_open_drain_on(data->base, gpio_mask(gpio));
+	} else {
+		mpc85xx_gpio_open_drain_off(data->base, gpio_mask(gpio));
+	}
+	return 0;
+}
+
+static int mpc85xx_gpio_get_function(struct udevice *dev, unsigned gpio)
+{
+	struct mpc85xx_gpio_data *data = dev_get_priv(dev);
+	int dir;
+
+	dir = !!mpc85xx_gpio_get_dir(data->base, gpio_mask(gpio));
+	return dir ? GPIOF_OUTPUT : GPIOF_INPUT;
+}
+
+static int mpc85xx_gpio_ofdata_to_platdata(struct udevice *dev) {
+	struct mpc85xx_gpio_data *data = dev_get_priv(dev);
+	fdt_addr_t addr;
+	fdt_size_t size;
+
+	addr = fdtdec_get_addr_size_auto_noparent(gd->fdt_blob, dev->of_offset,
+						  "reg", 0, &size);
+
+	data->addr = addr;
+	data->base = map_sysmem(CONFIG_SYS_IMMR + addr, size);
+
+	if (!data->base)
+		return -ENOMEM;
+
+	data->gpio_count = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+					  "ngpios", 32);
+	data->dat_shadow = 0;
+
+	return 0;
+}
+
+static int mpc85xx_gpio_probe(struct udevice *dev)
+{
+	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+	struct mpc85xx_gpio_data *data = dev_get_priv(dev);
+	char name[32], *str;
+
+	snprintf(name, sizeof(name), "MPC@%lx_", data->addr);
+	str = strdup(name);
+
+	if (!str)
+		return -ENOMEM;
+
+	uc_priv->bank_name = str;
+	uc_priv->gpio_count = data->gpio_count;
+
+	return 0;
+}
+
+static const struct dm_gpio_ops gpio_mpc85xx_ops = {
+	.direction_input	= mpc85xx_gpio_direction_input,
+	.direction_output	= mpc85xx_gpio_direction_output,
+	.get_value		= mpc85xx_gpio_get_value,
+	.set_value		= mpc85xx_gpio_set_value,
+	.get_open_drain		= mpc85xx_gpio_get_open_drain,
+	.set_open_drain		= mpc85xx_gpio_set_open_drain,
+	.get_function 		= mpc85xx_gpio_get_function,
+};
+
+static const struct udevice_id mpc85xx_gpio_ids[] = {
+	{ .compatible = "fsl,pq3-gpio" },
+	{ /* sentinel */ }
+};
+
+U_BOOT_DRIVER(gpio_mpc85xx) = {
+	.name	= "gpio_mpc85xx",
+	.id	= UCLASS_GPIO,
+	.ops	= &gpio_mpc85xx_ops,
+	.ofdata_to_platdata = mpc85xx_gpio_ofdata_to_platdata,
+	.of_match = mpc85xx_gpio_ids,
+	.probe	= mpc85xx_gpio_probe,
+	.priv_auto_alloc_size = sizeof(struct mpc85xx_gpio_data),
+};
diff --git a/drivers/gpio/rk_gpio.c b/drivers/gpio/rk_gpio.c
index fefe3ca..64abcba 100644
--- a/drivers/gpio/rk_gpio.c
+++ b/drivers/gpio/rk_gpio.c
@@ -8,7 +8,6 @@
  */
 
 #include <common.h>
-#include <clk.h>
 #include <dm.h>
 #include <syscon.h>
 #include <asm/errno.h>
diff --git a/drivers/gpio/sandbox.c b/drivers/gpio/sandbox.c
index a9b1efcd..f6435a0 100644
--- a/drivers/gpio/sandbox.c
+++ b/drivers/gpio/sandbox.c
@@ -15,6 +15,7 @@
 /* Flags for each GPIO */
 #define GPIOF_OUTPUT	(1 << 0)	/* Currently set as an output */
 #define GPIOF_HIGH	(1 << 1)	/* Currently set high */
+#define GPIOF_ODR	(1 << 2)	/* Currently set to open drain mode */
 
 struct gpio_state {
 	const char *label;	/* label given by requester */
@@ -70,6 +71,16 @@
 	return set_gpio_flag(dev, offset, GPIOF_HIGH, value);
 }
 
+int sandbox_gpio_get_open_drain(struct udevice *dev, unsigned offset)
+{
+	return get_gpio_flag(dev, offset, GPIOF_ODR);
+}
+
+int sandbox_gpio_set_open_drain(struct udevice *dev, unsigned offset, int value)
+{
+	return set_gpio_flag(dev, offset, GPIOF_ODR, value);
+}
+
 int sandbox_gpio_get_direction(struct udevice *dev, unsigned offset)
 {
 	return get_gpio_flag(dev, offset, GPIOF_OUTPUT);
@@ -124,6 +135,28 @@
 	return sandbox_gpio_set_value(dev, offset, value);
 }
 
+/* read GPIO ODR value of port 'offset' */
+static int sb_gpio_get_open_drain(struct udevice *dev, unsigned offset)
+{
+	debug("%s: offset:%u\n", __func__, offset);
+
+	return sandbox_gpio_get_open_drain(dev, offset);
+}
+
+/* write GPIO ODR value to port 'offset' */
+static int sb_gpio_set_open_drain(struct udevice *dev, unsigned offset, int value)
+{
+	debug("%s: offset:%u, value = %d\n", __func__, offset, value);
+
+	if (!sandbox_gpio_get_direction(dev, offset)) {
+		printf("sandbox_gpio: error: set_open_drain on input gpio %u\n",
+		       offset);
+		return -1;
+	}
+
+	return sandbox_gpio_set_open_drain(dev, offset, value);
+}
+
 static int sb_gpio_get_function(struct udevice *dev, unsigned offset)
 {
 	if (get_gpio_flag(dev, offset, GPIOF_OUTPUT))
@@ -154,6 +187,8 @@
 	.direction_output	= sb_gpio_direction_output,
 	.get_value		= sb_gpio_get_value,
 	.set_value		= sb_gpio_set_value,
+	.get_open_drain		= sb_gpio_get_open_drain,
+	.set_open_drain		= sb_gpio_set_open_drain,
 	.get_function		= sb_gpio_get_function,
 	.xlate			= sb_gpio_xlate,
 };
diff --git a/drivers/gpio/tegra186_gpio.c b/drivers/gpio/tegra186_gpio.c
new file mode 100644
index 0000000..1c68151
--- /dev/null
+++ b/drivers/gpio/tegra186_gpio.c
@@ -0,0 +1,288 @@
+/*
+ * Copyright (c) 2010-2016, NVIDIA CORPORATION.
+ * (based on tegra_gpio.c)
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <malloc.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <asm/io.h>
+#include <asm/bitops.h>
+#include <asm/gpio.h>
+#include <dm/device-internal.h>
+#include <dt-bindings/gpio/gpio.h>
+#include "tegra186_gpio_priv.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct tegra186_gpio_port_data {
+	const char *name;
+	uint32_t offset;
+};
+
+struct tegra186_gpio_ctlr_data {
+	const struct tegra186_gpio_port_data *ports;
+	uint32_t port_count;
+};
+
+struct tegra186_gpio_platdata {
+	const char *name;
+	uint32_t *regs;
+};
+
+static uint32_t *tegra186_gpio_reg(struct udevice *dev, uint32_t reg,
+				   uint32_t gpio)
+{
+	struct tegra186_gpio_platdata *plat = dev->platdata;
+	uint32_t index = (reg + (gpio * TEGRA186_GPIO_PER_GPIO_STRIDE)) / 4;
+
+	return &(plat->regs[index]);
+}
+
+static int tegra186_gpio_set_out(struct udevice *dev, unsigned offset,
+				 bool output)
+{
+	uint32_t *reg;
+	uint32_t rval;
+
+	reg = tegra186_gpio_reg(dev, TEGRA186_GPIO_OUTPUT_CONTROL, offset);
+	rval = readl(reg);
+	if (output)
+		rval &= ~TEGRA186_GPIO_OUTPUT_CONTROL_FLOATED;
+	else
+		rval |= TEGRA186_GPIO_OUTPUT_CONTROL_FLOATED;
+	writel(rval, reg);
+
+	reg = tegra186_gpio_reg(dev, TEGRA186_GPIO_ENABLE_CONFIG, offset);
+	rval = readl(reg);
+	if (output)
+		rval |= TEGRA186_GPIO_ENABLE_CONFIG_OUT;
+	else
+		rval &= ~TEGRA186_GPIO_ENABLE_CONFIG_OUT;
+	rval |= TEGRA186_GPIO_ENABLE_CONFIG_ENABLE;
+	writel(rval, reg);
+
+	return 0;
+}
+
+static int tegra186_gpio_set_val(struct udevice *dev, unsigned offset, bool val)
+{
+	uint32_t *reg;
+	uint32_t rval;
+
+	reg = tegra186_gpio_reg(dev, TEGRA186_GPIO_OUTPUT_VALUE, offset);
+	rval = readl(reg);
+	if (val)
+		rval |= TEGRA186_GPIO_OUTPUT_VALUE_HIGH;
+	else
+		rval &= ~TEGRA186_GPIO_OUTPUT_VALUE_HIGH;
+	writel(rval, reg);
+
+	return 0;
+}
+
+static int tegra186_gpio_direction_input(struct udevice *dev, unsigned offset)
+{
+	return tegra186_gpio_set_out(dev, offset, false);
+}
+
+static int tegra186_gpio_direction_output(struct udevice *dev, unsigned offset,
+				       int value)
+{
+	int ret;
+
+	ret = tegra186_gpio_set_val(dev, offset, value != 0);
+	if (ret)
+		return ret;
+	return tegra186_gpio_set_out(dev, offset, true);
+}
+
+static int tegra186_gpio_get_value(struct udevice *dev, unsigned offset)
+{
+	uint32_t *reg;
+	uint32_t rval;
+
+	reg = tegra186_gpio_reg(dev, TEGRA186_GPIO_ENABLE_CONFIG, offset);
+	rval = readl(reg);
+
+	if (rval & TEGRA186_GPIO_ENABLE_CONFIG_OUT)
+		reg = tegra186_gpio_reg(dev, TEGRA186_GPIO_OUTPUT_VALUE,
+					offset);
+	else
+		reg = tegra186_gpio_reg(dev, TEGRA186_GPIO_INPUT, offset);
+
+	rval = readl(reg);
+	return !!rval;
+}
+
+static int tegra186_gpio_set_value(struct udevice *dev, unsigned offset,
+				   int value)
+{
+	return tegra186_gpio_set_val(dev, offset, value != 0);
+}
+
+static int tegra186_gpio_get_function(struct udevice *dev, unsigned offset)
+{
+	uint32_t *reg;
+	uint32_t rval;
+
+	reg = tegra186_gpio_reg(dev, TEGRA186_GPIO_ENABLE_CONFIG, offset);
+	rval = readl(reg);
+	if (rval & TEGRA186_GPIO_ENABLE_CONFIG_OUT)
+		return GPIOF_OUTPUT;
+	else
+		return GPIOF_INPUT;
+}
+
+static int tegra186_gpio_xlate(struct udevice *dev, struct gpio_desc *desc,
+			    struct fdtdec_phandle_args *args)
+{
+	int gpio, port, ret;
+
+	gpio = args->args[0];
+	port = gpio / TEGRA186_GPIO_PER_GPIO_COUNT;
+	ret = device_get_child(dev, port, &desc->dev);
+	if (ret)
+		return ret;
+	desc->offset = gpio % TEGRA186_GPIO_PER_GPIO_COUNT;
+	desc->flags = args->args[1] & GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0;
+
+	return 0;
+}
+
+static const struct dm_gpio_ops tegra186_gpio_ops = {
+	.direction_input	= tegra186_gpio_direction_input,
+	.direction_output	= tegra186_gpio_direction_output,
+	.get_value		= tegra186_gpio_get_value,
+	.set_value		= tegra186_gpio_set_value,
+	.get_function		= tegra186_gpio_get_function,
+	.xlate			= tegra186_gpio_xlate,
+};
+
+/**
+ * We have a top-level GPIO device with no actual GPIOs. It has a child device
+ * for each port within the controller.
+ */
+static int tegra186_gpio_bind(struct udevice *parent)
+{
+	struct tegra186_gpio_platdata *parent_plat = parent->platdata;
+	struct tegra186_gpio_ctlr_data *ctlr_data =
+		(struct tegra186_gpio_ctlr_data *)dev_get_driver_data(parent);
+	uint32_t *regs;
+	int port, ret;
+
+	/* If this is a child device, there is nothing to do here */
+	if (parent_plat)
+		return 0;
+
+	regs = (uint32_t *)dev_get_addr_name(parent, "gpio");
+	if (regs == (uint32_t *)FDT_ADDR_T_NONE)
+		return -ENODEV;
+
+	for (port = 0; port < ctlr_data->port_count; port++) {
+		struct tegra186_gpio_platdata *plat;
+		struct udevice *dev;
+
+		plat = calloc(1, sizeof(*plat));
+		if (!plat)
+			return -ENOMEM;
+		plat->name = ctlr_data->ports[port].name;
+		plat->regs = &(regs[ctlr_data->ports[port].offset / 4]);
+
+		ret = device_bind(parent, parent->driver, plat->name, plat,
+				  -1, &dev);
+		if (ret)
+			return ret;
+		dev->of_offset = parent->of_offset;
+	}
+
+	return 0;
+}
+
+static int tegra186_gpio_probe(struct udevice *dev)
+{
+	struct tegra186_gpio_platdata *plat = dev->platdata;
+	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	/* Only child devices have ports */
+	if (!plat)
+		return 0;
+
+	uc_priv->gpio_count = TEGRA186_GPIO_PER_GPIO_COUNT;
+	uc_priv->bank_name = plat->name;
+
+	return 0;
+}
+
+static const struct tegra186_gpio_port_data tegra186_gpio_main_ports[] = {
+	{"A",  0x2000},
+	{"B",  0x3000},
+	{"C",  0x3200},
+	{"D",  0x3400},
+	{"E",  0x2200},
+	{"F",  0x2400},
+	{"G",  0x4200},
+	{"H",  0x1000},
+	{"I",  0x0800},
+	{"J",  0x5000},
+	{"K",  0x5200},
+	{"L",  0x1200},
+	{"M",  0x5600},
+	{"N",  0x0000},
+	{"O",  0x0200},
+	{"P",  0x4000},
+	{"Q",  0x0400},
+	{"R",  0x0a00},
+	{"T",  0x0600},
+	{"X",  0x1400},
+	{"Y",  0x1600},
+	{"BB", 0x2600},
+	{"CC", 0x5400},
+};
+
+static const struct tegra186_gpio_ctlr_data tegra186_gpio_main_data = {
+	.ports = tegra186_gpio_main_ports,
+	.port_count = ARRAY_SIZE(tegra186_gpio_main_ports),
+};
+
+static const struct tegra186_gpio_port_data tegra186_gpio_aon_ports[] = {
+	{"S",  0x0200},
+	{"U",  0x0400},
+	{"V",  0x0800},
+	{"W",  0x0a00},
+	{"Z",  0x0e00},
+	{"AA", 0x0c00},
+	{"EE", 0x0600},
+	{"FF", 0x0000},
+};
+
+static const struct tegra186_gpio_ctlr_data tegra186_gpio_aon_data = {
+	.ports = tegra186_gpio_aon_ports,
+	.port_count = ARRAY_SIZE(tegra186_gpio_aon_ports),
+};
+
+static const struct udevice_id tegra186_gpio_ids[] = {
+	{
+		.compatible = "nvidia,tegra186-gpio",
+		.data = (ulong)&tegra186_gpio_main_data,
+	},
+	{
+		.compatible = "nvidia,tegra186-gpio-aon",
+		.data = (ulong)&tegra186_gpio_aon_data,
+	},
+	{ }
+};
+
+U_BOOT_DRIVER(tegra186_gpio) = {
+	.name = "tegra186_gpio",
+	.id = UCLASS_GPIO,
+	.of_match = tegra186_gpio_ids,
+	.bind = tegra186_gpio_bind,
+	.probe = tegra186_gpio_probe,
+	.ops = &tegra186_gpio_ops,
+	.flags = DM_FLAG_PRE_RELOC,
+};
diff --git a/drivers/gpio/tegra186_gpio_priv.h b/drivers/gpio/tegra186_gpio_priv.h
new file mode 100644
index 0000000..9e85a434
--- /dev/null
+++ b/drivers/gpio/tegra186_gpio_priv.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2016, NVIDIA CORPORATION.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef _TEGRA186_GPIO_PRIV_H_
+#define _TEGRA186_GPIO_PRIV_H_
+
+/*
+ * For each GPIO, there are a set of registers than affect it, all packed
+ * back-to-back.
+ */
+#define TEGRA186_GPIO_ENABLE_CONFIG				0x00
+#define TEGRA186_GPIO_ENABLE_CONFIG_ENABLE			BIT(0)
+#define TEGRA186_GPIO_ENABLE_CONFIG_OUT				BIT(1)
+#define TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_SHIFT		2
+#define TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_MASK		3
+#define TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_NONE		0
+#define TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_LEVEL		1
+#define TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_SINGLE_EDGE	2
+#define TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_DOUBLE_EDGE	3
+#define TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_LEVEL_HIGH_RISING	BIT(4)
+#define TEGRA186_GPIO_ENABLE_CONFIG_DEBOUNCE_ENABLE		BIT(5)
+#define TEGRA186_GPIO_ENABLE_CONFIG_INTERRUPT_ENABLE		BIT(6)
+#define TEGRA186_GPIO_ENABLE_CONFIG_TIMESTAMPING_ENABLE		BIT(7)
+
+#define TEGRA186_GPIO_DEBOUNCE_THRESHOLD			0x04
+
+#define TEGRA186_GPIO_INPUT					0x08
+
+#define TEGRA186_GPIO_OUTPUT_CONTROL				0x0c
+#define TEGRA186_GPIO_OUTPUT_CONTROL_FLOATED			BIT(0)
+
+#define TEGRA186_GPIO_OUTPUT_VALUE				0x10
+#define TEGRA186_GPIO_OUTPUT_VALUE_HIGH				1
+
+#define TEGRA186_GPIO_INTERRUPT_CLEAR				0x14
+
+/*
+ * 8 GPIOs are packed into a port. Their registers appear back-to-back in the
+ * port's address space.
+ */
+#define TEGRA186_GPIO_PER_GPIO_STRIDE				0x20
+#define TEGRA186_GPIO_PER_GPIO_COUNT				8
+
+/*
+ * Per-port registers are packed immediately following all of a port's
+ * per-GPIO registers.
+ */
+#define TEGRA186_GPIO_INTERRUPT_STATUS_G			0x100
+#define TEGRA186_GPIO_INTERRUPT_STATUS_G_STRIDE			4
+#define TEGRA186_GPIO_INTERRUPT_STATUS_G_COUNT			8
+
+/*
+ * The registers for multiple ports are packed together back-to-back to form
+ * the overall controller.
+ */
+#define TEGRA186_GPIO_PER_PORT_STRIDE				0x200
+
+#endif
diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c
index 3acf9e8..57ad975 100644
--- a/drivers/mmc/fsl_esdhc.c
+++ b/drivers/mmc/fsl_esdhc.c
@@ -308,14 +308,10 @@
 static void check_and_invalidate_dcache_range
 	(struct mmc_cmd *cmd,
 	 struct mmc_data *data) {
-#ifdef CONFIG_FSL_LAYERSCAPE
 	unsigned start = 0;
-#else
-	unsigned start = (unsigned)data->dest ;
-#endif
+	unsigned end = 0;
 	unsigned size = roundup(ARCH_DMA_MINALIGN,
 				data->blocks*data->blocksize);
-	unsigned end = start+size ;
 #ifdef CONFIG_FSL_LAYERSCAPE
 	dma_addr_t addr;
 
@@ -324,7 +320,10 @@
 		printf("Error found for upper 32 bits\n");
 	else
 		start = lower_32_bits(addr);
+#else
+	start = (unsigned)data->dest;
 #endif
+	end = start + size;
 	invalidate_dcache_range(start, end);
 }
 
diff --git a/drivers/mmc/tegra_mmc.c b/drivers/mmc/tegra_mmc.c
index 573819a..c9d9432 100644
--- a/drivers/mmc/tegra_mmc.c
+++ b/drivers/mmc/tegra_mmc.c
@@ -11,8 +11,10 @@
 #include <common.h>
 #include <asm/gpio.h>
 #include <asm/io.h>
+#ifndef CONFIG_TEGRA186
 #include <asm/arch/clock.h>
 #include <asm/arch-tegra/clk_rst.h>
+#endif
 #include <asm/arch-tegra/mmc.h>
 #include <asm/arch-tegra/tegra_mmc.h>
 #include <mmc.h>
@@ -357,8 +359,12 @@
 	 */
 	if (clock == 0)
 		goto out;
+#ifndef CONFIG_TEGRA186
 	clock_adjust_periph_pll_div(host->mmc_id, CLOCK_ID_PERIPH, clock,
 				    &div);
+#else
+	div = (20000000 + clock - 1) / clock;
+#endif
 	debug("div = %d\n", div);
 
 	writew(0, &host->reg->clkcon);
@@ -543,7 +549,9 @@
 	      gpio_get_number(&host->cd_gpio));
 
 	host->clock = 0;
+#ifndef CONFIG_TEGRA186
 	clock_start_periph_pll(host->mmc_id, CLOCK_ID_PERIPH, 20000000);
+#endif
 
 	if (dm_gpio_is_valid(&host->pwr_gpio))
 		dm_gpio_set_value(&host->pwr_gpio, 1);
@@ -568,7 +576,11 @@
 	 *  (actually 52MHz)
 	 */
 	host->cfg.f_min = 375000;
+#ifndef CONFIG_TEGRA186
 	host->cfg.f_max = 48000000;
+#else
+	host->cfg.f_max = 375000;
+#endif
 
 	host->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
 
@@ -600,11 +612,13 @@
 		return -FDT_ERR_NOTFOUND;
 	}
 
+#ifndef CONFIG_TEGRA186
 	host->mmc_id = clock_decode_periph_id(blob, node);
 	if (host->mmc_id == PERIPH_ID_NONE) {
 		debug("%s: could not decode periph id\n", __func__);
 		return -FDT_ERR_NOTFOUND;
 	}
+#endif
 
 	/*
 	 * NOTE: mmc->bus_width is determined by mmc.c dynamically.
@@ -624,7 +638,13 @@
 	*removablep = !fdtdec_get_bool(blob, node, "non-removable");
 
 	debug("%s: found controller at %p, width = %d, periph_id = %d\n",
-		__func__, host->reg, host->width, host->mmc_id);
+		__func__, host->reg, host->width,
+#ifndef CONFIG_TEGRA186
+		host->mmc_id
+#else
+		-1
+#endif
+	);
 	return 0;
 }
 
@@ -668,6 +688,16 @@
 	const void *blob = gd->fdt_blob;
 	debug("%s entry\n", __func__);
 
+	/* See if any Tegra186 MMC controllers are present */
+	count = fdtdec_find_aliases_for_id(blob, "sdhci",
+		COMPAT_NVIDIA_TEGRA186_SDMMC, node_list,
+		CONFIG_SYS_MMC_MAX_DEVICE);
+	debug("%s: count of Tegra186 sdhci nodes is %d\n", __func__, count);
+	if (process_nodes(blob, node_list, count)) {
+		printf("%s: Error processing T186 mmc node(s)!\n", __func__);
+		return;
+	}
+
 	/* See if any Tegra210 MMC controllers are present */
 	count = fdtdec_find_aliases_for_id(blob, "sdhci",
 		COMPAT_NVIDIA_TEGRA210_SDMMC, node_list,
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 6fb3718..837d397 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -13,7 +13,6 @@
 
 obj-$(CONFIG_SPL_NAND_AM33XX_BCH) += am335x_spl_bch.o
 obj-$(CONFIG_SPL_NAND_DENALI) += denali_spl.o
-obj-$(CONFIG_SPL_NAND_DOCG4) += docg4_spl.o
 obj-$(CONFIG_SPL_NAND_SIMPLE) += nand_spl_simple.o
 obj-$(CONFIG_SPL_NAND_LOAD) += nand_spl_load.o
 obj-$(CONFIG_SPL_NAND_ECC) += nand_ecc.o
@@ -50,7 +49,6 @@
 obj-$(CONFIG_NAND_FSL_IFC) += fsl_ifc_nand.o
 obj-$(CONFIG_NAND_FSL_UPM) += fsl_upm.o
 obj-$(CONFIG_NAND_FSMC) += fsmc_nand.o
-obj-$(CONFIG_NAND_JZ4740) += jz4740_nand.o
 obj-$(CONFIG_NAND_KB9202) += kb9202_nand.o
 obj-$(CONFIG_NAND_KIRKWOOD) += kirkwood_nand.o
 obj-$(CONFIG_NAND_KMETER1) += kmeter1_nand.o
@@ -68,7 +66,6 @@
 obj-$(CONFIG_NAND_OMAP_GPMC) += omap_gpmc.o
 obj-$(CONFIG_NAND_OMAP_ELM) += omap_elm.o
 obj-$(CONFIG_NAND_PLAT) += nand_plat.o
-obj-$(CONFIG_NAND_DOCG4) += docg4.o
 
 else  # minimal SPL drivers
 
diff --git a/drivers/mtd/nand/am335x_spl_bch.c b/drivers/mtd/nand/am335x_spl_bch.c
index 31c7825..f8770e0 100644
--- a/drivers/mtd/nand/am335x_spl_bch.c
+++ b/drivers/mtd/nand/am335x_spl_bch.c
@@ -16,7 +16,7 @@
 #include <linux/mtd/nand_ecc.h>
 
 static int nand_ecc_pos[] = CONFIG_SYS_NAND_ECCPOS;
-nand_info_t nand_info[1];
+static struct mtd_info *mtd;
 static struct nand_chip nand_chip;
 
 #define ECCSTEPS	(CONFIG_SYS_NAND_PAGE_SIZE / \
@@ -30,12 +30,12 @@
 static int nand_command(int block, int page, uint32_t offs,
 	u8 cmd)
 {
-	struct nand_chip *this = nand_info[0].priv;
+	struct nand_chip *this = mtd_to_nand(mtd);
 	int page_addr = page + block * CONFIG_SYS_NAND_PAGE_COUNT;
 	void (*hwctrl)(struct mtd_info *mtd, int cmd,
 			unsigned int ctrl) = this->cmd_ctrl;
 
-	while (!this->dev_ready(&nand_info[0]))
+	while (!this->dev_ready(mtd))
 		;
 
 	/* Emulate NAND_CMD_READOOB */
@@ -45,11 +45,11 @@
 	}
 
 	/* Begin command latch cycle */
-	hwctrl(&nand_info[0], cmd, NAND_CTRL_CLE | NAND_CTRL_CHANGE);
+	hwctrl(mtd, cmd, NAND_CTRL_CLE | NAND_CTRL_CHANGE);
 
 	if (cmd == NAND_CMD_RESET) {
-		hwctrl(&nand_info[0], NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
-		while (!this->dev_ready(&nand_info[0]))
+		hwctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
+		while (!this->dev_ready(mtd))
 			;
 		return 0;
 	}
@@ -60,39 +60,39 @@
 
 	/* Set ALE and clear CLE to start address cycle */
 	/* Column address */
-	hwctrl(&nand_info[0], offs & 0xff,
+	hwctrl(mtd, offs & 0xff,
 		       NAND_CTRL_ALE | NAND_CTRL_CHANGE); /* A[7:0] */
-	hwctrl(&nand_info[0], (offs >> 8) & 0xff, NAND_CTRL_ALE); /* A[11:9] */
+	hwctrl(mtd, (offs >> 8) & 0xff, NAND_CTRL_ALE); /* A[11:9] */
 	/* Row address */
 	if (cmd != NAND_CMD_RNDOUT) {
-		hwctrl(&nand_info[0], (page_addr & 0xff),
+		hwctrl(mtd, (page_addr & 0xff),
 		       NAND_CTRL_ALE); /* A[19:12] */
-		hwctrl(&nand_info[0], ((page_addr >> 8) & 0xff),
+		hwctrl(mtd, ((page_addr >> 8) & 0xff),
 		       NAND_CTRL_ALE); /* A[27:20] */
 #ifdef CONFIG_SYS_NAND_5_ADDR_CYCLE
 		/* One more address cycle for devices > 128MiB */
-		hwctrl(&nand_info[0], (page_addr >> 16) & 0x0f,
+		hwctrl(mtd, (page_addr >> 16) & 0x0f,
 		       NAND_CTRL_ALE); /* A[31:28] */
 #endif
 	}
 
-	hwctrl(&nand_info[0], NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
+	hwctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
 
 	if (cmd == NAND_CMD_READ0) {
 		/* Latch in address */
-		hwctrl(&nand_info[0], NAND_CMD_READSTART,
+		hwctrl(mtd, NAND_CMD_READSTART,
 			   NAND_CTRL_CLE | NAND_CTRL_CHANGE);
-		hwctrl(&nand_info[0], NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
+		hwctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
 
 		/*
 		 * Wait a while for the data to be ready
 		 */
-		while (!this->dev_ready(&nand_info[0]))
+		while (!this->dev_ready(mtd))
 			;
 	} else if (cmd == NAND_CMD_RNDOUT) {
-		hwctrl(&nand_info[0], NAND_CMD_RNDOUTSTART, NAND_CTRL_CLE |
+		hwctrl(mtd, NAND_CMD_RNDOUTSTART, NAND_CTRL_CLE |
 					NAND_CTRL_CHANGE);
-		hwctrl(&nand_info[0], NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
+		hwctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
 	}
 
 	return 0;
@@ -100,7 +100,7 @@
 
 static int nand_is_bad_block(int block)
 {
-	struct nand_chip *this = nand_info[0].priv;
+	struct nand_chip *this = mtd_to_nand(mtd);
 
 	nand_command(block, 0, CONFIG_SYS_NAND_BAD_BLOCK_POS,
 		NAND_CMD_READOOB);
@@ -121,7 +121,7 @@
 
 static int nand_read_page(int block, int page, void *dst)
 {
-	struct nand_chip *this = nand_info[0].priv;
+	struct nand_chip *this = mtd_to_nand(mtd);
 	u_char ecc_calc[ECCTOTAL];
 	u_char ecc_code[ECCTOTAL];
 	u_char oob_data[CONFIG_SYS_NAND_OOBSIZE];
@@ -137,15 +137,15 @@
 	nand_command(block, page, 0, NAND_CMD_READ0);
 
 	for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
-		this->ecc.hwctl(&nand_info[0], NAND_ECC_READ);
+		this->ecc.hwctl(mtd, NAND_ECC_READ);
 		nand_command(block, page, data_pos, NAND_CMD_RNDOUT);
 
-		this->read_buf(&nand_info[0], p, eccsize);
+		this->read_buf(mtd, p, eccsize);
 
 		nand_command(block, page, oob_pos, NAND_CMD_RNDOUT);
 
-		this->read_buf(&nand_info[0], oob, eccbytes);
-		this->ecc.calculate(&nand_info[0], p, &ecc_calc[i]);
+		this->read_buf(mtd, oob, eccbytes);
+		this->ecc.calculate(mtd, p, &ecc_calc[i]);
 
 		data_pos += eccsize;
 		oob_pos += eccbytes;
@@ -164,7 +164,7 @@
 		 * from correct_data(). We just hope that all possible errors
 		 * are corrected by this routine.
 		 */
-		this->ecc.correct(&nand_info[0], p, &ecc_code[i], &ecc_calc[i]);
+		this->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
 	}
 
 	return 0;
@@ -223,13 +223,13 @@
 	/*
 	 * Init board specific nand support
 	 */
-	nand_info[0].priv = &nand_chip;
+	mtd = &nand_chip.mtd;
 	nand_chip.IO_ADDR_R = nand_chip.IO_ADDR_W =
 		(void  __iomem *)CONFIG_SYS_NAND_BASE;
 	board_nand_init(&nand_chip);
 
 	if (nand_chip.select_chip)
-		nand_chip.select_chip(&nand_info[0], 0);
+		nand_chip.select_chip(mtd, 0);
 
 	/* NAND chip may require reset after power-on */
 	nand_command(0, 0, 0, NAND_CMD_RESET);
@@ -239,5 +239,5 @@
 void nand_deselect(void)
 {
 	if (nand_chip.select_chip)
-		nand_chip.select_chip(&nand_info[0], -1);
+		nand_chip.select_chip(mtd, -1);
 }
diff --git a/drivers/mtd/nand/arasan_nfc.c b/drivers/mtd/nand/arasan_nfc.c
index 2d73a05..320cbaa 100644
--- a/drivers/mtd/nand/arasan_nfc.c
+++ b/drivers/mtd/nand/arasan_nfc.c
@@ -230,7 +230,7 @@
 static u8 arasan_nand_get_addrcycle(struct mtd_info *mtd)
 {
 	u8 addrcycles;
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 
 	switch (curr_cmd->addr_cycles) {
 	case NAND_ADDR_CYCL_NONE:
@@ -264,7 +264,7 @@
 
 static int arasan_nand_read_page(struct mtd_info *mtd, u8 *buf, u32 size)
 {
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 	u32 reg_val, i, pktsize, pktnum;
 	u32 *bufptr = (u32 *)buf;
 	u32 timeout;
@@ -433,7 +433,8 @@
 }
 
 static int arasan_nand_write_page_hwecc(struct mtd_info *mtd,
-		struct nand_chip *chip, const u8 *buf, int oob_required)
+		struct nand_chip *chip, const u8 *buf, int oob_required,
+		int page)
 {
 	u32 reg_val, i, pktsize, pktnum;
 	const u32 *bufptr = (const u32 *)buf;
@@ -441,7 +442,7 @@
 	u32 size = mtd->writesize;
 	u32 rdcount = 0;
 	u8 column_addr_cycles;
-	struct arasan_nand_info *nand = chip->priv;
+	struct arasan_nand_info *nand = nand_get_controller_data(chip);
 
 	if (chip->ecc_step_ds >= ARASAN_NAND_PKTSIZE_1K)
 		pktsize = ARASAN_NAND_PKTSIZE_1K;
@@ -944,7 +945,7 @@
 
 static u8 arasan_nand_read_byte(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 	u32 size;
 	u8 val;
 	struct nand_onfi_params *p;
@@ -976,8 +977,8 @@
 				     int column, int page_addr)
 {
 	u32 i, ret = 0;
-	struct nand_chip *chip = mtd->priv;
-	struct arasan_nand_info *nand = chip->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct arasan_nand_info *nand = nand_get_controller_data(chip);
 
 	curr_cmd = NULL;
 	writel(ARASAN_NAND_INT_STS_XFR_CMPLT_MASK,
@@ -1033,7 +1034,7 @@
 {
 	int found = -1;
 	u32 regval, eccpos_start, i;
-	struct nand_chip *nand_chip = mtd->priv;
+	struct nand_chip *nand_chip = mtd_to_nand(mtd);
 
 	nand_chip->ecc.mode = NAND_ECC_HW;
 	nand_chip->ecc.hwctl = NULL;
@@ -1058,20 +1059,20 @@
 	if (found < 0)
 		return 1;
 
-	regval = ecc_matrix[i].eccaddr |
-		 (ecc_matrix[i].eccsize << ARASAN_NAND_ECC_SIZE_SHIFT) |
-		 (ecc_matrix[i].bch << ARASAN_NAND_ECC_BCH_SHIFT);
+	regval = ecc_matrix[found].eccaddr |
+		 (ecc_matrix[found].eccsize << ARASAN_NAND_ECC_SIZE_SHIFT) |
+		 (ecc_matrix[found].bch << ARASAN_NAND_ECC_BCH_SHIFT);
 	writel(regval, &arasan_nand_base->ecc_reg);
 
-	if (ecc_matrix[i].bch) {
+	if (ecc_matrix[found].bch) {
 		regval = readl(&arasan_nand_base->memadr_reg2);
 		regval &= ~ARASAN_NAND_MEM_ADDR2_BCH_MASK;
-		regval |= (ecc_matrix[i].bchval <<
+		regval |= (ecc_matrix[found].bchval <<
 			   ARASAN_NAND_MEM_ADDR2_BCH_SHIFT);
 		writel(regval, &arasan_nand_base->memadr_reg2);
 	}
 
-	nand_oob.eccbytes = ecc_matrix[i].eccsize;
+	nand_oob.eccbytes = ecc_matrix[found].eccsize;
 	eccpos_start = mtd->oobsize - nand_oob.eccbytes;
 
 	for (i = 0; i < nand_oob.eccbytes; i++)
@@ -1080,9 +1081,9 @@
 	nand_oob.oobfree[0].offset = 2;
 	nand_oob.oobfree[0].length = eccpos_start - 2;
 
-	nand_chip->ecc.size = ecc_matrix[i].ecc_codeword_size;
-	nand_chip->ecc.strength = ecc_matrix[i].eccbits;
-	nand_chip->ecc.bytes = ecc_matrix[i].eccsize;
+	nand_chip->ecc.size = ecc_matrix[found].ecc_codeword_size;
+	nand_chip->ecc.strength = ecc_matrix[found].eccbits;
+	nand_chip->ecc.bytes = ecc_matrix[found].eccsize;
 	nand_chip->ecc.layout = &nand_oob;
 
 	return 0;
@@ -1101,9 +1102,8 @@
 	}
 
 	nand->nand_base = arasan_nand_base;
-	mtd = &nand_info[0];
-	nand_chip->priv = nand;
-	mtd->priv = nand_chip;
+	mtd = nand_to_mtd(nand_chip);
+	nand_set_controller_data(nand_chip, nand);
 
 	/* Set the driver entry points for MTD */
 	nand_chip->cmdfunc = arasan_nand_cmd_function;
@@ -1134,7 +1134,7 @@
 		goto fail;
 	}
 
-	if (nand_register(devnum)) {
+	if (nand_register(devnum, mtd)) {
 		printf("Nand Register Fail\n");
 		goto fail;
 	}
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index 7cc1de0..75e8307 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -160,8 +160,8 @@
 
 static void pmecc_gen_syndrome(struct mtd_info *mtd, int sector)
 {
-	struct nand_chip *nand_chip = mtd->priv;
-	struct atmel_nand_host *host = nand_chip->priv;
+	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct atmel_nand_host *host = nand_get_controller_data(nand_chip);
 	int i;
 	uint32_t value;
 
@@ -177,8 +177,8 @@
 
 static void pmecc_substitute(struct mtd_info *mtd)
 {
-	struct nand_chip *nand_chip = mtd->priv;
-	struct atmel_nand_host *host = nand_chip->priv;
+	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct atmel_nand_host *host = nand_get_controller_data(nand_chip);
 	int16_t __iomem *alpha_to = host->pmecc_alpha_to;
 	int16_t __iomem *index_of = host->pmecc_index_of;
 	int16_t *partial_syn = host->pmecc_partial_syn;
@@ -227,8 +227,8 @@
  */
 static void pmecc_get_sigma(struct mtd_info *mtd)
 {
-	struct nand_chip *nand_chip = mtd->priv;
-	struct atmel_nand_host *host = nand_chip->priv;
+	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct atmel_nand_host *host = nand_get_controller_data(nand_chip);
 
 	int16_t *lmu = host->pmecc_lmu;
 	int16_t *si = host->pmecc_si;
@@ -383,8 +383,8 @@
 
 static int pmecc_err_location(struct mtd_info *mtd)
 {
-	struct nand_chip *nand_chip = mtd->priv;
-	struct atmel_nand_host *host = nand_chip->priv;
+	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct atmel_nand_host *host = nand_get_controller_data(nand_chip);
 	const int cap = host->pmecc_corr_cap;
 	const int num = 2 * cap + 1;
 	int sector_size = host->pmecc_sector_size;
@@ -437,8 +437,8 @@
 static void pmecc_correct_data(struct mtd_info *mtd, uint8_t *buf, uint8_t *ecc,
 		int sector_num, int extra_bytes, int err_nbr)
 {
-	struct nand_chip *nand_chip = mtd->priv;
-	struct atmel_nand_host *host = nand_chip->priv;
+	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct atmel_nand_host *host = nand_get_controller_data(nand_chip);
 	int i = 0;
 	int byte_pos, bit_pos, sector_size, pos;
 	uint32_t tmp;
@@ -483,8 +483,8 @@
 static int pmecc_correction(struct mtd_info *mtd, u32 pmecc_stat, uint8_t *buf,
 	u8 *ecc)
 {
-	struct nand_chip *nand_chip = mtd->priv;
-	struct atmel_nand_host *host = nand_chip->priv;
+	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct atmel_nand_host *host = nand_get_controller_data(nand_chip);
 	int i, err_nbr, eccbytes;
 	uint8_t *buf_pos;
 
@@ -513,7 +513,7 @@
 			if (err_nbr == -1) {
 				dev_err(host->dev, "PMECC: Too many errors\n");
 				mtd->ecc_stats.failed++;
-				return -EIO;
+				return -EBADMSG;
 			} else {
 				pmecc_correct_data(mtd, buf_pos, ecc, i,
 					host->pmecc_bytes_per_sector, err_nbr);
@@ -529,7 +529,7 @@
 static int atmel_nand_pmecc_read_page(struct mtd_info *mtd,
 	struct nand_chip *chip, uint8_t *buf, int oob_required, int page)
 {
-	struct atmel_nand_host *host = chip->priv;
+	struct atmel_nand_host *host = nand_get_controller_data(chip);
 	int eccsize = chip->ecc.size;
 	uint8_t *oob = chip->oob_poi;
 	uint32_t *eccpos = chip->ecc.layout->eccpos;
@@ -562,16 +562,16 @@
 	stat = pmecc_readl(host->pmecc, isr);
 	if (stat != 0)
 		if (pmecc_correction(mtd, stat, buf, &oob[eccpos[0]]) != 0)
-			return -EIO;
+			return -EBADMSG;
 
 	return 0;
 }
 
 static int atmel_nand_pmecc_write_page(struct mtd_info *mtd,
 		struct nand_chip *chip, const uint8_t *buf,
-		int oob_required)
+		int oob_required, int page)
 {
-	struct atmel_nand_host *host = chip->priv;
+	struct atmel_nand_host *host = nand_get_controller_data(chip);
 	uint32_t *eccpos = chip->ecc.layout->eccpos;
 	int i, j;
 	int timeout = PMECC_MAX_TIMEOUT_US;
@@ -615,8 +615,8 @@
 
 static void atmel_pmecc_core_init(struct mtd_info *mtd)
 {
-	struct nand_chip *nand_chip = mtd->priv;
-	struct atmel_nand_host *host = nand_chip->priv;
+	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct atmel_nand_host *host = nand_get_controller_data(nand_chip);
 	uint32_t val = 0;
 	struct nand_ecclayout *ecc_layout;
 
@@ -808,7 +808,8 @@
 	struct atmel_nand_host *host;
 	int cap, sector_size;
 
-	host = nand->priv = &pmecc_host;
+	host = &pmecc_host;
+	nand_set_controller_data(nand, host);
 
 	nand->ecc.mode = NAND_ECC_HW;
 	nand->ecc.calculate = NULL;
@@ -1080,7 +1081,7 @@
 static int atmel_nand_correct(struct mtd_info *mtd, u_char *dat,
 		u_char *read_ecc, u_char *isnull)
 {
-	struct nand_chip *nand_chip = mtd->priv;
+	struct nand_chip *nand_chip = mtd_to_nand(mtd);
 	unsigned int ecc_status;
 	unsigned int ecc_word, ecc_bit;
 
@@ -1111,7 +1112,7 @@
 		 * We can't correct so many errors */
 		dev_warn(host->dev, "atmel_nand : multiple errors detected."
 				" Unable to correct.\n");
-		return -EIO;
+		return -EBADMSG;
 	}
 
 	/* if there's a single bit error : we can correct it */
@@ -1207,7 +1208,7 @@
 static void at91_nand_hwcontrol(struct mtd_info *mtd,
 					 int cmd, unsigned int ctrl)
 {
-	struct nand_chip *this = mtd->priv;
+	struct nand_chip *this = mtd_to_nand(mtd);
 
 	if (ctrl & NAND_CTRL_CHANGE) {
 		ulong IO_ADDR_W = (ulong) this->IO_ADDR_W;
@@ -1238,17 +1239,17 @@
 
 #ifdef CONFIG_SPL_BUILD
 /* The following code is for SPL */
-static nand_info_t mtd;
+static struct mtd_info *mtd;
 static struct nand_chip nand_chip;
 
 static int nand_command(int block, int page, uint32_t offs, u8 cmd)
 {
-	struct nand_chip *this = mtd.priv;
+	struct nand_chip *this = mtd_to_nand(mtd);
 	int page_addr = page + block * CONFIG_SYS_NAND_PAGE_COUNT;
 	void (*hwctrl)(struct mtd_info *mtd, int cmd,
 			unsigned int ctrl) = this->cmd_ctrl;
 
-	while (!this->dev_ready(&mtd))
+	while (!this->dev_ready(mtd))
 		;
 
 	if (cmd == NAND_CMD_READOOB) {
@@ -1256,24 +1257,24 @@
 		cmd = NAND_CMD_READ0;
 	}
 
-	hwctrl(&mtd, cmd, NAND_CTRL_CLE | NAND_CTRL_CHANGE);
+	hwctrl(mtd, cmd, NAND_CTRL_CLE | NAND_CTRL_CHANGE);
 
 	if ((this->options & NAND_BUSWIDTH_16) && !nand_opcode_8bits(cmd))
 		offs >>= 1;
 
-	hwctrl(&mtd, offs & 0xff, NAND_CTRL_ALE | NAND_CTRL_CHANGE);
-	hwctrl(&mtd, (offs >> 8) & 0xff, NAND_CTRL_ALE);
-	hwctrl(&mtd, (page_addr & 0xff), NAND_CTRL_ALE);
-	hwctrl(&mtd, ((page_addr >> 8) & 0xff), NAND_CTRL_ALE);
+	hwctrl(mtd, offs & 0xff, NAND_CTRL_ALE | NAND_CTRL_CHANGE);
+	hwctrl(mtd, (offs >> 8) & 0xff, NAND_CTRL_ALE);
+	hwctrl(mtd, (page_addr & 0xff), NAND_CTRL_ALE);
+	hwctrl(mtd, ((page_addr >> 8) & 0xff), NAND_CTRL_ALE);
 #ifdef CONFIG_SYS_NAND_5_ADDR_CYCLE
-	hwctrl(&mtd, (page_addr >> 16) & 0x0f, NAND_CTRL_ALE);
+	hwctrl(mtd, (page_addr >> 16) & 0x0f, NAND_CTRL_ALE);
 #endif
-	hwctrl(&mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
+	hwctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
 
-	hwctrl(&mtd, NAND_CMD_READSTART, NAND_CTRL_CLE | NAND_CTRL_CHANGE);
-	hwctrl(&mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
+	hwctrl(mtd, NAND_CMD_READSTART, NAND_CTRL_CLE | NAND_CTRL_CHANGE);
+	hwctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
 
-	while (!this->dev_ready(&mtd))
+	while (!this->dev_ready(mtd))
 		;
 
 	return 0;
@@ -1281,7 +1282,7 @@
 
 static int nand_is_bad_block(int block)
 {
-	struct nand_chip *this = mtd.priv;
+	struct nand_chip *this = mtd_to_nand(mtd);
 
 	nand_command(block, 0, CONFIG_SYS_NAND_BAD_BLOCK_POS, NAND_CMD_READOOB);
 
@@ -1304,7 +1305,7 @@
 
 static int nand_read_page(int block, int page, void *dst)
 {
-	struct nand_chip *this = mtd.priv;
+	struct nand_chip *this = mtd_to_nand(mtd);
 	u_char ecc_calc[ECCTOTAL];
 	u_char ecc_code[ECCTOTAL];
 	u_char oob_data[CONFIG_SYS_NAND_OOBSIZE];
@@ -1317,11 +1318,11 @@
 
 	for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
 		if (this->ecc.mode != NAND_ECC_SOFT)
-			this->ecc.hwctl(&mtd, NAND_ECC_READ);
-		this->read_buf(&mtd, p, eccsize);
-		this->ecc.calculate(&mtd, p, &ecc_calc[i]);
+			this->ecc.hwctl(mtd, NAND_ECC_READ);
+		this->read_buf(mtd, p, eccsize);
+		this->ecc.calculate(mtd, p, &ecc_calc[i]);
 	}
-	this->read_buf(&mtd, oob_data, CONFIG_SYS_NAND_OOBSIZE);
+	this->read_buf(mtd, oob_data, CONFIG_SYS_NAND_OOBSIZE);
 
 	for (i = 0; i < ECCTOTAL; i++)
 		ecc_code[i] = oob_data[nand_ecc_pos[i]];
@@ -1330,35 +1331,35 @@
 	p = dst;
 
 	for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize)
-		this->ecc.correct(&mtd, p, &ecc_code[i], &ecc_calc[i]);
+		this->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
 
 	return 0;
 }
 
 int spl_nand_erase_one(int block, int page)
 {
-	struct nand_chip *this = mtd.priv;
+	struct nand_chip *this = mtd_to_nand(mtd);
 	void (*hwctrl)(struct mtd_info *mtd, int cmd,
 			unsigned int ctrl) = this->cmd_ctrl;
 	int page_addr;
 
 	if (nand_chip.select_chip)
-		nand_chip.select_chip(&mtd, 0);
+		nand_chip.select_chip(mtd, 0);
 
 	page_addr = page + block * CONFIG_SYS_NAND_PAGE_COUNT;
-	hwctrl(&mtd, NAND_CMD_ERASE1, NAND_CTRL_CLE | NAND_CTRL_CHANGE);
+	hwctrl(mtd, NAND_CMD_ERASE1, NAND_CTRL_CLE | NAND_CTRL_CHANGE);
 	/* Row address */
-	hwctrl(&mtd, (page_addr & 0xff), NAND_CTRL_ALE | NAND_CTRL_CHANGE);
-	hwctrl(&mtd, ((page_addr >> 8) & 0xff),
+	hwctrl(mtd, (page_addr & 0xff), NAND_CTRL_ALE | NAND_CTRL_CHANGE);
+	hwctrl(mtd, ((page_addr >> 8) & 0xff),
 	       NAND_CTRL_ALE | NAND_CTRL_CHANGE);
 #ifdef CONFIG_SYS_NAND_5_ADDR_CYCLE
 	/* One more address cycle for devices > 128MiB */
-	hwctrl(&mtd, (page_addr >> 16) & 0x0f,
+	hwctrl(mtd, (page_addr >> 16) & 0x0f,
 	       NAND_CTRL_ALE | NAND_CTRL_CHANGE);
 #endif
-	hwctrl(&mtd, NAND_CMD_ERASE2, NAND_CTRL_CLE | NAND_CTRL_CHANGE);
+	hwctrl(mtd, NAND_CMD_ERASE2, NAND_CTRL_CLE | NAND_CTRL_CHANGE);
 
-	while (!this->dev_ready(&mtd))
+	while (!this->dev_ready(mtd))
 		;
 
 	nand_deselect();
@@ -1368,10 +1369,10 @@
 #else
 static int nand_read_page(int block, int page, void *dst)
 {
-	struct nand_chip *this = mtd.priv;
+	struct nand_chip *this = mtd_to_nand(mtd);
 
 	nand_command(block, page, 0, NAND_CMD_READ0);
-	atmel_nand_pmecc_read_page(&mtd, this, dst, 0, page);
+	atmel_nand_pmecc_read_page(mtd, this, dst, 0, page);
 
 	return 0;
 }
@@ -1407,7 +1408,7 @@
 
 int at91_nand_wait_ready(struct mtd_info *mtd)
 {
-	struct nand_chip *this = mtd->priv;
+	struct nand_chip *this = mtd_to_nand(mtd);
 
 	udelay(this->chip_delay);
 
@@ -1438,7 +1439,7 @@
 
 #ifdef CONFIG_ATMEL_NAND_HWECC
 #ifdef CONFIG_ATMEL_NAND_HW_PMECC
-	ret = atmel_pmecc_nand_init_params(nand, &mtd);
+	ret = atmel_pmecc_nand_init_params(nand, mtd);
 #endif
 #endif
 
@@ -1447,9 +1448,9 @@
 
 void nand_init(void)
 {
-	mtd.writesize = CONFIG_SYS_NAND_PAGE_SIZE;
-	mtd.oobsize = CONFIG_SYS_NAND_OOBSIZE;
-	mtd.priv = &nand_chip;
+	mtd = &nand_chip.mtd;
+	mtd->writesize = CONFIG_SYS_NAND_PAGE_SIZE;
+	mtd->oobsize = CONFIG_SYS_NAND_OOBSIZE;
 	nand_chip.IO_ADDR_R = (void __iomem *)CONFIG_SYS_NAND_BASE;
 	nand_chip.IO_ADDR_W = (void __iomem *)CONFIG_SYS_NAND_BASE;
 	board_nand_init(&nand_chip);
@@ -1462,13 +1463,13 @@
 #endif
 
 	if (nand_chip.select_chip)
-		nand_chip.select_chip(&mtd, 0);
+		nand_chip.select_chip(mtd, 0);
 }
 
 void nand_deselect(void)
 {
 	if (nand_chip.select_chip)
-		nand_chip.select_chip(&mtd, -1);
+		nand_chip.select_chip(mtd, -1);
 }
 
 #else
@@ -1482,10 +1483,9 @@
 int atmel_nand_chip_init(int devnum, ulong base_addr)
 {
 	int ret;
-	struct mtd_info *mtd = &nand_info[devnum];
 	struct nand_chip *nand = &nand_chip[devnum];
+	struct mtd_info *mtd = nand_to_mtd(nand);
 
-	mtd->priv = nand;
 	nand->IO_ADDR_R = nand->IO_ADDR_W = (void  __iomem *)base_addr;
 
 #ifdef CONFIG_NAND_ECC_BCH
@@ -1521,7 +1521,7 @@
 
 	ret = nand_scan_tail(mtd);
 	if (!ret)
-		nand_register(devnum);
+		nand_register(devnum, mtd);
 
 	return ret;
 }
diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c
index a397074..48a8ca7 100644
--- a/drivers/mtd/nand/davinci_nand.c
+++ b/drivers/mtd/nand/davinci_nand.c
@@ -54,7 +54,7 @@
  */
 static void nand_davinci_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 {
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 	const u32 *nand = chip->IO_ADDR_R;
 
 	/* Make sure that buf is 32 bit aligned */
@@ -99,7 +99,7 @@
 static void nand_davinci_write_buf(struct mtd_info *mtd, const uint8_t *buf,
 				   int len)
 {
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 	const u32 *nand = chip->IO_ADDR_W;
 
 	/* Make sure that buf is 32 bit aligned */
@@ -144,7 +144,7 @@
 static void nand_davinci_hwcontrol(struct mtd_info *mtd, int cmd,
 		unsigned int ctrl)
 {
-	struct		nand_chip *this = mtd->priv;
+	struct		nand_chip *this = mtd_to_nand(mtd);
 	u_int32_t	IO_ADDR_W = (u_int32_t)this->IO_ADDR_W;
 
 	if (ctrl & NAND_CTRL_CHANGE) {
@@ -223,7 +223,7 @@
 static int nand_davinci_correct_data(struct mtd_info *mtd, u_char *dat,
 		u_char *read_ecc, u_char *calc_ecc)
 {
-	struct nand_chip *this = mtd->priv;
+	struct nand_chip *this = mtd_to_nand(mtd);
 	u_int32_t ecc_nand = read_ecc[0] | (read_ecc[1] << 8) |
 					  (read_ecc[2] << 16);
 	u_int32_t ecc_calc = calc_ecc[0] | (calc_ecc[1] << 8) |
@@ -243,7 +243,7 @@
 					 "%d\n", find_byte, find_bit);
 				return 1;
 			} else {
-				return -1;
+				return -EBADMSG;
 			}
 		} else if (!(diff & (diff - 1))) {
 			/* Single bit ECC error in the ECC itself,
@@ -254,7 +254,7 @@
 		} else {
 			/* Uncorrectable error */
 			MTDDEBUG(MTD_DEBUG_LEVEL0, "ECC UNCORRECTED_ERROR 1\n");
-			return -1;
+			return -EBADMSG;
 		}
 	}
 	return 0;
@@ -380,10 +380,13 @@
 
 	chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
 
-	if (unlikely(raw))
-		status = chip->ecc.write_page_raw(mtd, chip, buf, oob_required);
-	else
-		status = chip->ecc.write_page(mtd, chip, buf, oob_required);
+	if (unlikely(raw)) {
+		status = chip->ecc.write_page_raw(mtd, chip, buf,
+						  oob_required, page);
+	} else {
+		status = chip->ecc.write_page(mtd, chip, buf,
+					      oob_required, page);
+	}
 
 	if (status < 0) {
 		ret = status;
@@ -698,7 +701,7 @@
 		return 0;
 	} else if (iserror == ECC_STATE_TOO_MANY_ERRS) {
 		val = __raw_readl(&davinci_emif_regs->nanderrval1);
-		return -1;
+		return -EBADMSG;
 	}
 
 	numerrors = ((__raw_readl(&davinci_emif_regs->nandfsr) >> 16)
diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
index 5894fcc..601e744 100644
--- a/drivers/mtd/nand/denali.c
+++ b/drivers/mtd/nand/denali.c
@@ -48,7 +48,10 @@
  * this macro allows us to convert from an MTD structure to our own
  * device context (denali) structure.
  */
-#define mtd_to_denali(m) container_of(m->priv, struct denali_nand_info, nand)
+static inline struct denali_nand_info *mtd_to_denali(struct mtd_info *mtd)
+{
+	return container_of(mtd_to_nand(mtd), struct denali_nand_info, nand);
+}
 
 /*
  * These constants are defined by the driver to enable common driver
@@ -865,7 +868,7 @@
  * by write_page above.
  */
 static int denali_write_page(struct mtd_info *mtd, struct nand_chip *chip,
-				const uint8_t *buf, int oob_required)
+				const uint8_t *buf, int oob_required, int page)
 {
 	struct denali_nand_info *denali = mtd_to_denali(mtd);
 
@@ -889,7 +892,8 @@
  * write_page() function above.
  */
 static int denali_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
-					const uint8_t *buf, int oob_required)
+				 const uint8_t *buf, int oob_required,
+				 int page)
 {
 	struct denali_nand_info *denali = mtd_to_denali(mtd);
 
@@ -988,7 +992,7 @@
 			debug("  ECC error cause by erased block\n");
 			/* false alarm, return the 0xFF */
 		} else {
-			return -EIO;
+			return -EBADMSG;
 		}
 	}
 	memcpy(buf, denali->buf.dma_buf, mtd->writesize);
@@ -1173,13 +1177,13 @@
 
 static int denali_init(struct denali_nand_info *denali)
 {
+	struct mtd_info *mtd = nand_to_mtd(&denali->nand);
 	int ret;
 
 	denali_hw_init(denali);
 
-	denali->mtd->name = "denali-nand";
-	denali->mtd->owner = THIS_MODULE;
-	denali->mtd->priv = &denali->nand;
+	mtd->name = "denali-nand";
+	mtd->owner = THIS_MODULE;
 
 	/* register the driver with the NAND core subsystem */
 	denali->nand.select_chip = denali_select_chip;
@@ -1193,7 +1197,7 @@
 	 * this is the first stage in a two step process to register
 	 * with the nand subsystem
 	 */
-	if (nand_scan_ident(denali->mtd, denali->max_banks, NULL)) {
+	if (nand_scan_ident(mtd, denali->max_banks, NULL)) {
 		ret = -ENXIO;
 		goto fail;
 	}
@@ -1239,13 +1243,13 @@
 	nand_oob.eccbytes = denali->nand.ecc.bytes;
 	denali->nand.ecc.layout = &nand_oob;
 
-	writel(denali->mtd->erasesize / denali->mtd->writesize,
+	writel(mtd->erasesize / mtd->writesize,
 	       denali->flash_reg + PAGES_PER_BLOCK);
 	writel(denali->nand.options & NAND_BUSWIDTH_16 ? 1 : 0,
 	       denali->flash_reg + DEVICE_WIDTH);
-	writel(denali->mtd->writesize,
+	writel(mtd->writesize,
 	       denali->flash_reg + DEVICE_MAIN_AREA_SIZE);
-	writel(denali->mtd->oobsize,
+	writel(mtd->oobsize,
 	       denali->flash_reg + DEVICE_SPARE_AREA_SIZE);
 	if (readl(denali->flash_reg + DEVICES_CONNECTED) == 0)
 		writel(1, denali->flash_reg + DEVICES_CONNECTED);
@@ -1258,12 +1262,12 @@
 	denali->nand.ecc.read_oob = denali_read_oob;
 	denali->nand.ecc.write_oob = denali_write_oob;
 
-	if (nand_scan_tail(denali->mtd)) {
+	if (nand_scan_tail(mtd)) {
 		ret = -ENXIO;
 		goto fail;
 	}
 
-	ret = nand_register(0);
+	ret = nand_register(0, mtd);
 
 fail:
 	return ret;
@@ -1278,13 +1282,6 @@
 		return -ENOMEM;
 
 	/*
-	 * If CONFIG_SYS_NAND_SELF_INIT is defined, each driver is responsible
-	 * for instantiating struct nand_chip, while drivers/mtd/nand/nand.c
-	 * still provides a "struct mtd_info nand_info" instance.
-	 */
-	denali->mtd = &nand_info[0];
-
-	/*
 	 * In the future, these base addresses should be taken from
 	 * Device Tree or platform data.
 	 */
diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h
index db1457a..0e098bd 100644
--- a/drivers/mtd/nand/denali.h
+++ b/drivers/mtd/nand/denali.h
@@ -436,7 +436,6 @@
 #define DT		3
 
 struct denali_nand_info {
-	struct mtd_info *mtd;
 	struct nand_chip nand;
 	int flash_bank; /* currently selected chip */
 	int status;
diff --git a/drivers/mtd/nand/denali_spl.c b/drivers/mtd/nand/denali_spl.c
index 1587413..c693032 100644
--- a/drivers/mtd/nand/denali_spl.c
+++ b/drivers/mtd/nand/denali_spl.c
@@ -41,7 +41,7 @@
 
 		if (intr_status & INTR_STATUS__ECC_UNCOR_ERR) {
 			debug("Uncorrected ECC detected\n");
-			return -EIO;
+			return -EBADMSG;
 		}
 
 		if (intr_status & irq_mask)
diff --git a/drivers/mtd/nand/docg4.c b/drivers/mtd/nand/docg4.c
deleted file mode 100644
index c1c1ff8..0000000
--- a/drivers/mtd/nand/docg4.c
+++ /dev/null
@@ -1,1030 +0,0 @@
-/*
- * drivers/mtd/nand/docg4.c
- *
- * Copyright (C) 2013 Mike Dunn <mikedunn@newsguy.com>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- *
- * mtd nand driver for M-Systems DiskOnChip G4
- *
- * Tested on the Palm Treo 680.  The G4 is also present on Toshiba Portege, Asus
- * P526, some HTC smartphones (Wizard, Prophet, ...), O2 XDA Zinc, maybe others.
- * Should work on these as well.  Let me know!
- *
- * TODO:
- *
- *  Mechanism for management of password-protected areas
- *
- *  Hamming ecc when reading oob only
- *
- *  According to the M-Sys documentation, this device is also available in a
- *  "dual-die" configuration having a 256MB capacity, but no mechanism for
- *  detecting this variant is documented.  Currently this driver assumes 128MB
- *  capacity.
- *
- *  Support for multiple cascaded devices ("floors").  Not sure which gadgets
- *  contain multiple G4s in a cascaded configuration, if any.
- */
-
-
-#include <common.h>
-#include <asm/arch/hardware.h>
-#include <asm/io.h>
-#include <asm/bitops.h>
-#include <asm/errno.h>
-#include <malloc.h>
-#include <nand.h>
-#include <linux/bch.h>
-#include <linux/bitrev.h>
-#include <linux/mtd/docg4.h>
-
-/*
- * The device has a nop register which M-Sys claims is for the purpose of
- * inserting precise delays.  But beware; at least some operations fail if the
- * nop writes are replaced with a generic delay!
- */
-static inline void write_nop(void __iomem *docptr)
-{
-	writew(0, docptr + DOC_NOP);
-}
-
-
-static int poll_status(void __iomem *docptr)
-{
-	/*
-	 * Busy-wait for the FLASHREADY bit to be set in the FLASHCONTROL
-	 * register.  Operations known to take a long time (e.g., block erase)
-	 * should sleep for a while before calling this.
-	 */
-
-	uint8_t flash_status;
-
-	/* hardware quirk requires reading twice initially */
-	flash_status = readb(docptr + DOC_FLASHCONTROL);
-
-	do {
-		flash_status = readb(docptr + DOC_FLASHCONTROL);
-	} while (!(flash_status & DOC_CTRL_FLASHREADY));
-
-	return 0;
-}
-
-static void write_addr(void __iomem *docptr, uint32_t docg4_addr)
-{
-	/* write the four address bytes packed in docg4_addr to the device */
-
-	writeb(docg4_addr & 0xff, docptr + DOC_FLASHADDRESS);
-	docg4_addr >>= 8;
-	writeb(docg4_addr & 0xff, docptr + DOC_FLASHADDRESS);
-	docg4_addr >>= 8;
-	writeb(docg4_addr & 0xff, docptr + DOC_FLASHADDRESS);
-	docg4_addr >>= 8;
-	writeb(docg4_addr & 0xff, docptr + DOC_FLASHADDRESS);
-}
-
-/*
- * This is a module parameter in the linux kernel version of this driver.  It is
- * hard-coded to 'off' for u-boot.  This driver uses oob to mark bad blocks.
- * This can be problematic when dealing with data not intended for the mtd/nand
- * subsystem.  For example, on boards that boot from the docg4 and use the IPL
- * to load an spl + u-boot image, the blocks containing the image will be
- * reported as "bad" because the oob of the first page of each block contains a
- * magic number that the IPL looks for, which causes the badblock scan to
- * erroneously add them to the bad block table.  To erase such a block, use
- * u-boot's 'nand scrub'.  scrub is safe for the docg4.  The device does have a
- * factory bad block table, but it is read-only, and is used in conjunction with
- * oob bad block markers that are written by mtd/nand when a block is deemed to
- * be bad.  To read data from "bad" blocks, use 'read.raw'.  Unfortunately,
- * read.raw does not use ecc, which would still work fine on such misidentified
- * bad blocks.  TODO: u-boot nand utilities need the ability to ignore bad
- * blocks.
- */
-static const int ignore_badblocks; /* remains false */
-
-struct docg4_priv {
-	int status;
-	struct {
-		unsigned int command;
-		int column;
-		int page;
-	} last_command;
-	uint8_t oob_buf[16];
-	uint8_t ecc_buf[7];
-	int oob_page;
-	struct bch_control *bch;
-};
-/*
- * Oob bytes 0 - 6 are available to the user.
- * Byte 7 is hamming ecc for first 7 bytes.  Bytes 8 - 14 are hw-generated ecc.
- * Byte 15 (the last) is used by the driver as a "page written" flag.
- */
-static struct nand_ecclayout docg4_oobinfo = {
-	.eccbytes = 9,
-	.eccpos = {7, 8, 9, 10, 11, 12, 13, 14, 15},
-	.oobavail = 7,
-	.oobfree = { {0, 7} }
-};
-
-static void reset(void __iomem *docptr)
-{
-	/* full device reset */
-
-	writew(DOC_ASICMODE_RESET | DOC_ASICMODE_MDWREN, docptr + DOC_ASICMODE);
-	writew(~(DOC_ASICMODE_RESET | DOC_ASICMODE_MDWREN),
-	       docptr + DOC_ASICMODECONFIRM);
-	write_nop(docptr);
-
-	writew(DOC_ASICMODE_NORMAL | DOC_ASICMODE_MDWREN,
-	       docptr + DOC_ASICMODE);
-	writew(~(DOC_ASICMODE_NORMAL | DOC_ASICMODE_MDWREN),
-	       docptr + DOC_ASICMODECONFIRM);
-
-	writew(DOC_ECCCONF1_ECC_ENABLE, docptr + DOC_ECCCONF1);
-
-	poll_status(docptr);
-}
-
-static void docg4_select_chip(struct mtd_info *mtd, int chip)
-{
-	/*
-	 * Select among multiple cascaded chips ("floors").  Multiple floors are
-	 * not yet supported, so the only valid non-negative value is 0.
-	 */
-	void __iomem *docptr = CONFIG_SYS_NAND_BASE;
-
-	if (chip < 0)
-		return;		/* deselected */
-
-	if (chip > 0)
-		printf("multiple floors currently unsupported\n");
-
-	writew(0, docptr + DOC_DEVICESELECT);
-}
-
-static void read_hw_ecc(void __iomem *docptr, uint8_t *ecc_buf)
-{
-	/* read the 7 hw-generated ecc bytes */
-
-	int i;
-	for (i = 0; i < 7; i++) { /* hw quirk; read twice */
-		ecc_buf[i] = readb(docptr + DOC_BCH_SYNDROM(i));
-		ecc_buf[i] = readb(docptr + DOC_BCH_SYNDROM(i));
-	}
-}
-
-static int correct_data(struct mtd_info *mtd, uint8_t *buf, int page)
-{
-	/*
-	 * Called after a page read when hardware reports bitflips.
-	 * Up to four bitflips can be corrected.
-	 */
-
-	struct nand_chip *nand = mtd->priv;
-	struct docg4_priv *doc = nand->priv;
-	void __iomem *docptr = CONFIG_SYS_NAND_BASE;
-	int i, numerrs;
-	unsigned int errpos[4];
-	const uint8_t blank_read_hwecc[8] = {
-		0xcf, 0x72, 0xfc, 0x1b, 0xa9, 0xc7, 0xb9, 0 };
-
-	read_hw_ecc(docptr, doc->ecc_buf); /* read 7 hw-generated ecc bytes */
-
-	/* check if read error is due to a blank page */
-	if (!memcmp(doc->ecc_buf, blank_read_hwecc, 7))
-		return 0;	/* yes */
-
-	/* skip additional check of "written flag" if ignore_badblocks */
-	if (!ignore_badblocks) {
-		/*
-		 * If the hw ecc bytes are not those of a blank page, there's
-		 * still a chance that the page is blank, but was read with
-		 * errors.  Check the "written flag" in last oob byte, which
-		 * is set to zero when a page is written.  If more than half
-		 * the bits are set, assume a blank page.  Unfortunately, the
-		 * bit flips(s) are not reported in stats.
-		 */
-
-		if (doc->oob_buf[15]) {
-			int bit, numsetbits = 0;
-			unsigned long written_flag = doc->oob_buf[15];
-
-			for (bit = 0; bit < 8; bit++) {
-				if (written_flag & 0x01)
-					numsetbits++;
-				written_flag >>= 1;
-			}
-			if (numsetbits > 4) { /* assume blank */
-				printf("errors in blank page at offset %08x\n",
-				       page * DOCG4_PAGE_SIZE);
-				return 0;
-			}
-		}
-	}
-
-	/*
-	 * The hardware ecc unit produces oob_ecc ^ calc_ecc.  The kernel's bch
-	 * algorithm is used to decode this.  However the hw operates on page
-	 * data in a bit order that is the reverse of that of the bch alg,
-	 * requiring that the bits be reversed on the result.  Thanks to Ivan
-	 * Djelic for his analysis!
-	 */
-	for (i = 0; i < 7; i++)
-		doc->ecc_buf[i] = bitrev8(doc->ecc_buf[i]);
-
-	numerrs = decode_bch(doc->bch, NULL, DOCG4_USERDATA_LEN, NULL,
-			     doc->ecc_buf, NULL, errpos);
-
-	if (numerrs == -EBADMSG) {
-		printf("uncorrectable errors at offset %08x\n",
-		       page * DOCG4_PAGE_SIZE);
-		return -EBADMSG;
-	}
-
-	BUG_ON(numerrs < 0);	/* -EINVAL, or anything other than -EBADMSG */
-
-	/* undo last step in BCH alg (modulo mirroring not needed) */
-	for (i = 0; i < numerrs; i++)
-		errpos[i] = (errpos[i] & ~7)|(7-(errpos[i] & 7));
-
-	/* fix the errors */
-	for (i = 0; i < numerrs; i++) {
-		/* ignore if error within oob ecc bytes */
-		if (errpos[i] > DOCG4_USERDATA_LEN * 8)
-			continue;
-
-		/* if error within oob area preceeding ecc bytes... */
-		if (errpos[i] > DOCG4_PAGE_SIZE * 8)
-			__change_bit(errpos[i] - DOCG4_PAGE_SIZE * 8,
-				     (unsigned long *)doc->oob_buf);
-
-		else    /* error in page data */
-			__change_bit(errpos[i], (unsigned long *)buf);
-	}
-
-	printf("%d error(s) corrected at offset %08x\n",
-	       numerrs, page * DOCG4_PAGE_SIZE);
-
-	return numerrs;
-}
-
-static int read_progstatus(struct docg4_priv *doc, void __iomem *docptr)
-{
-	/*
-	 * This apparently checks the status of programming.  Done after an
-	 * erasure, and after page data is written.  On error, the status is
-	 * saved, to be later retrieved by the nand infrastructure code.
-	 */
-
-	/* status is read from the I/O reg */
-	uint16_t status1 = readw(docptr + DOC_IOSPACE_DATA);
-	uint16_t status2 = readw(docptr + DOC_IOSPACE_DATA);
-	uint16_t status3 = readw(docptr + DOCG4_MYSTERY_REG);
-
-	MTDDEBUG(MTD_DEBUG_LEVEL3, "docg4: %s: %02x %02x %02x\n",
-	    __func__, status1, status2, status3);
-
-	if (status1 != DOCG4_PROGSTATUS_GOOD ||
-	    status2 != DOCG4_PROGSTATUS_GOOD_2 ||
-	    status3 != DOCG4_PROGSTATUS_GOOD_2) {
-		doc->status = NAND_STATUS_FAIL;
-		printf("read_progstatus failed: %02x, %02x, %02x\n",
-		       status1, status2, status3);
-		return -EIO;
-	}
-	return 0;
-}
-
-static int pageprog(struct mtd_info *mtd)
-{
-	/*
-	 * Final step in writing a page.  Writes the contents of its
-	 * internal buffer out to the flash array, or some such.
-	 */
-
-	struct nand_chip *nand = mtd->priv;
-	struct docg4_priv *doc = nand->priv;
-	void __iomem *docptr = CONFIG_SYS_NAND_BASE;
-	int retval = 0;
-
-	MTDDEBUG(MTD_DEBUG_LEVEL3, "docg4: %s\n", __func__);
-
-	writew(DOCG4_SEQ_PAGEPROG, docptr + DOC_FLASHSEQUENCE);
-	writew(DOC_CMD_PROG_CYCLE2, docptr + DOC_FLASHCOMMAND);
-	write_nop(docptr);
-	write_nop(docptr);
-
-	/* Just busy-wait; usleep_range() slows things down noticeably. */
-	poll_status(docptr);
-
-	writew(DOCG4_SEQ_FLUSH, docptr + DOC_FLASHSEQUENCE);
-	writew(DOCG4_CMD_FLUSH, docptr + DOC_FLASHCOMMAND);
-	writew(DOC_ECCCONF0_READ_MODE | 4, docptr + DOC_ECCCONF0);
-	write_nop(docptr);
-	write_nop(docptr);
-	write_nop(docptr);
-	write_nop(docptr);
-	write_nop(docptr);
-
-	retval = read_progstatus(doc, docptr);
-	writew(0, docptr + DOC_DATAEND);
-	write_nop(docptr);
-	poll_status(docptr);
-	write_nop(docptr);
-
-	return retval;
-}
-
-static void sequence_reset(void __iomem *docptr)
-{
-	/* common starting sequence for all operations */
-
-	writew(DOC_CTRL_UNKNOWN | DOC_CTRL_CE, docptr + DOC_FLASHCONTROL);
-	writew(DOC_SEQ_RESET, docptr + DOC_FLASHSEQUENCE);
-	writew(DOC_CMD_RESET, docptr + DOC_FLASHCOMMAND);
-	write_nop(docptr);
-	write_nop(docptr);
-	poll_status(docptr);
-	write_nop(docptr);
-}
-
-static void read_page_prologue(void __iomem *docptr, uint32_t docg4_addr)
-{
-	/* first step in reading a page */
-
-	sequence_reset(docptr);
-
-	writew(DOCG4_SEQ_PAGE_READ, docptr + DOC_FLASHSEQUENCE);
-	writew(DOCG4_CMD_PAGE_READ, docptr + DOC_FLASHCOMMAND);
-	write_nop(docptr);
-
-	write_addr(docptr, docg4_addr);
-
-	write_nop(docptr);
-	writew(DOCG4_CMD_READ2, docptr + DOC_FLASHCOMMAND);
-	write_nop(docptr);
-	write_nop(docptr);
-
-	poll_status(docptr);
-}
-
-static void write_page_prologue(void __iomem *docptr, uint32_t docg4_addr)
-{
-	/* first step in writing a page */
-
-	sequence_reset(docptr);
-	writew(DOCG4_SEQ_PAGEWRITE, docptr + DOC_FLASHSEQUENCE);
-	writew(DOCG4_CMD_PAGEWRITE, docptr + DOC_FLASHCOMMAND);
-	write_nop(docptr);
-	write_addr(docptr, docg4_addr);
-	write_nop(docptr);
-	write_nop(docptr);
-	poll_status(docptr);
-}
-
-static uint32_t mtd_to_docg4_address(int page, int column)
-{
-	/*
-	 * Convert mtd address to format used by the device, 32 bit packed.
-	 *
-	 * Some notes on G4 addressing... The M-Sys documentation on this device
-	 * claims that pages are 2K in length, and indeed, the format of the
-	 * address used by the device reflects that.  But within each page are
-	 * four 512 byte "sub-pages", each with its own oob data that is
-	 * read/written immediately after the 512 bytes of page data.  This oob
-	 * data contains the ecc bytes for the preceeding 512 bytes.
-	 *
-	 * Rather than tell the mtd nand infrastructure that page size is 2k,
-	 * with four sub-pages each, we engage in a little subterfuge and tell
-	 * the infrastructure code that pages are 512 bytes in size.  This is
-	 * done because during the course of reverse-engineering the device, I
-	 * never observed an instance where an entire 2K "page" was read or
-	 * written as a unit.  Each "sub-page" is always addressed individually,
-	 * its data read/written, and ecc handled before the next "sub-page" is
-	 * addressed.
-	 *
-	 * This requires us to convert addresses passed by the mtd nand
-	 * infrastructure code to those used by the device.
-	 *
-	 * The address that is written to the device consists of four bytes: the
-	 * first two are the 2k page number, and the second is the index into
-	 * the page.  The index is in terms of 16-bit half-words and includes
-	 * the preceeding oob data, so e.g., the index into the second
-	 * "sub-page" is 0x108, and the full device address of the start of mtd
-	 * page 0x201 is 0x00800108.
-	 */
-	int g4_page = page / 4;	                      /* device's 2K page */
-	int g4_index = (page % 4) * 0x108 + column/2; /* offset into page */
-	return (g4_page << 16) | g4_index;	      /* pack */
-}
-
-static void docg4_command(struct mtd_info *mtd, unsigned command, int column,
-			  int page_addr)
-{
-	/* handle standard nand commands */
-
-	struct nand_chip *nand = mtd->priv;
-	struct docg4_priv *doc = nand->priv;
-	uint32_t g4_addr = mtd_to_docg4_address(page_addr, column);
-
-	MTDDEBUG(MTD_DEBUG_LEVEL3, "%s %x, page_addr=%x, column=%x\n",
-	    __func__, command, page_addr, column);
-
-	/*
-	 * Save the command and its arguments.  This enables emulation of
-	 * standard flash devices, and also some optimizations.
-	 */
-	doc->last_command.command = command;
-	doc->last_command.column = column;
-	doc->last_command.page = page_addr;
-
-	switch (command) {
-	case NAND_CMD_RESET:
-		reset(CONFIG_SYS_NAND_BASE);
-		break;
-
-	case NAND_CMD_READ0:
-		read_page_prologue(CONFIG_SYS_NAND_BASE, g4_addr);
-		break;
-
-	case NAND_CMD_STATUS:
-		/* next call to read_byte() will expect a status */
-		break;
-
-	case NAND_CMD_SEQIN:
-		write_page_prologue(CONFIG_SYS_NAND_BASE, g4_addr);
-
-		/* hack for deferred write of oob bytes */
-		if (doc->oob_page == page_addr)
-			memcpy(nand->oob_poi, doc->oob_buf, 16);
-		break;
-
-	case NAND_CMD_PAGEPROG:
-		pageprog(mtd);
-		break;
-
-	/* we don't expect these, based on review of nand_base.c */
-	case NAND_CMD_READOOB:
-	case NAND_CMD_READID:
-	case NAND_CMD_ERASE1:
-	case NAND_CMD_ERASE2:
-		printf("docg4_command: unexpected nand command 0x%x\n",
-		       command);
-		break;
-	}
-}
-
-static void docg4_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
-{
-	int i;
-	struct nand_chip *nand = mtd->priv;
-	uint16_t *p = (uint16_t *)buf;
-	len >>= 1;
-
-	for (i = 0; i < len; i++)
-		p[i] = readw(nand->IO_ADDR_R);
-}
-
-static int docg4_read_oob(struct mtd_info *mtd, struct nand_chip *nand,
-			  int page)
-{
-	struct docg4_priv *doc = nand->priv;
-	void __iomem *docptr = CONFIG_SYS_NAND_BASE;
-	uint16_t status;
-
-	MTDDEBUG(MTD_DEBUG_LEVEL3, "%s: page %x\n", __func__, page);
-
-	/*
-	 * Oob bytes are read as part of a normal page read.  If the previous
-	 * nand command was a read of the page whose oob is now being read, just
-	 * copy the oob bytes that we saved in a local buffer and avoid a
-	 * separate oob read.
-	 */
-	if (doc->last_command.command == NAND_CMD_READ0 &&
-	    doc->last_command.page == page) {
-		memcpy(nand->oob_poi, doc->oob_buf, 16);
-		return 0;
-	}
-
-	/*
-	 * Separate read of oob data only.
-	 */
-	docg4_command(mtd, NAND_CMD_READ0, nand->ecc.size, page);
-
-	writew(DOC_ECCCONF0_READ_MODE | DOCG4_OOB_SIZE, docptr + DOC_ECCCONF0);
-	write_nop(docptr);
-	write_nop(docptr);
-	write_nop(docptr);
-	write_nop(docptr);
-	write_nop(docptr);
-
-	/* the 1st byte from the I/O reg is a status; the rest is oob data */
-	status = readw(docptr + DOC_IOSPACE_DATA);
-	if (status & DOCG4_READ_ERROR) {
-		printf("docg4_read_oob failed: status = 0x%02x\n", status);
-		return -EIO;
-	}
-
-	MTDDEBUG(MTD_DEBUG_LEVEL3, "%s: status = 0x%x\n", __func__, status);
-
-	docg4_read_buf(mtd, nand->oob_poi, 16);
-
-	write_nop(docptr);
-	write_nop(docptr);
-	write_nop(docptr);
-	writew(0, docptr + DOC_DATAEND);
-	write_nop(docptr);
-
-	return 0;
-}
-
-static int docg4_write_oob(struct mtd_info *mtd, struct nand_chip *nand,
-			   int page)
-{
-	/*
-	 * Writing oob-only is not really supported, because MLC nand must write
-	 * oob bytes at the same time as page data.  Nonetheless, we save the
-	 * oob buffer contents here, and then write it along with the page data
-	 * if the same page is subsequently written.  This allows user space
-	 * utilities that write the oob data prior to the page data to work
-	 * (e.g., nandwrite).  The disdvantage is that, if the intention was to
-	 * write oob only, the operation is quietly ignored.  Also, oob can get
-	 * corrupted if two concurrent processes are running nandwrite.
-	 */
-
-	/* note that bytes 7..14 are hw generated hamming/ecc and overwritten */
-	struct docg4_priv *doc = nand->priv;
-	doc->oob_page = page;
-	memcpy(doc->oob_buf, nand->oob_poi, 16);
-	return 0;
-}
-
-static int docg4_block_neverbad(struct mtd_info *mtd, loff_t ofs, int getchip)
-{
-	/* only called when module_param ignore_badblocks is set */
-	return 0;
-}
-
-static void docg4_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
-{
-	int i;
-	struct nand_chip *nand = mtd->priv;
-	uint16_t *p = (uint16_t *)buf;
-	len >>= 1;
-
-	for (i = 0; i < len; i++)
-		writew(p[i], nand->IO_ADDR_W);
-}
-
-static int write_page(struct mtd_info *mtd, struct nand_chip *nand,
-		       const uint8_t *buf, int use_ecc)
-{
-	void __iomem *docptr = CONFIG_SYS_NAND_BASE;
-	uint8_t ecc_buf[8];
-
-	writew(DOC_ECCCONF0_ECC_ENABLE |
-	       DOC_ECCCONF0_UNKNOWN |
-	       DOCG4_BCH_SIZE,
-	       docptr + DOC_ECCCONF0);
-	write_nop(docptr);
-
-	/* write the page data */
-	docg4_write_buf16(mtd, buf, DOCG4_PAGE_SIZE);
-
-	/* oob bytes 0 through 5 are written to I/O reg */
-	docg4_write_buf16(mtd, nand->oob_poi, 6);
-
-	/* oob byte 6 written to a separate reg */
-	writew(nand->oob_poi[6], docptr + DOCG4_OOB_6_7);
-
-	write_nop(docptr);
-	write_nop(docptr);
-
-	/* write hw-generated ecc bytes to oob */
-	if (likely(use_ecc)) {
-		/* oob byte 7 is hamming code */
-		uint8_t hamming = readb(docptr + DOC_HAMMINGPARITY);
-		hamming = readb(docptr + DOC_HAMMINGPARITY); /* 2nd read */
-		writew(hamming, docptr + DOCG4_OOB_6_7);
-		write_nop(docptr);
-
-		/* read the 7 bch bytes from ecc regs */
-		read_hw_ecc(docptr, ecc_buf);
-		ecc_buf[7] = 0;         /* clear the "page written" flag */
-	}
-
-	/* write user-supplied bytes to oob */
-	else {
-		writew(nand->oob_poi[7], docptr + DOCG4_OOB_6_7);
-		write_nop(docptr);
-		memcpy(ecc_buf, &nand->oob_poi[8], 8);
-	}
-
-	docg4_write_buf16(mtd, ecc_buf, 8);
-	write_nop(docptr);
-	write_nop(docptr);
-	writew(0, docptr + DOC_DATAEND);
-	write_nop(docptr);
-
-	return 0;
-}
-
-static int docg4_write_page_raw(struct mtd_info *mtd, struct nand_chip *nand,
-				 const uint8_t *buf, int oob_required)
-{
-	return write_page(mtd, nand, buf, 0);
-}
-
-static int docg4_write_page(struct mtd_info *mtd, struct nand_chip *nand,
-			     const uint8_t *buf, int oob_required)
-{
-	return write_page(mtd, nand, buf, 1);
-}
-
-static int read_page(struct mtd_info *mtd, struct nand_chip *nand,
-		     uint8_t *buf, int page, int use_ecc)
-{
-	struct docg4_priv *doc = nand->priv;
-	void __iomem *docptr = CONFIG_SYS_NAND_BASE;
-	uint16_t status, edc_err, *buf16;
-
-	writew(DOC_ECCCONF0_READ_MODE |
-	       DOC_ECCCONF0_ECC_ENABLE |
-	       DOC_ECCCONF0_UNKNOWN |
-	       DOCG4_BCH_SIZE,
-	       docptr + DOC_ECCCONF0);
-	write_nop(docptr);
-	write_nop(docptr);
-	write_nop(docptr);
-	write_nop(docptr);
-	write_nop(docptr);
-
-	/* the 1st byte from the I/O reg is a status; the rest is page data */
-	status = readw(docptr + DOC_IOSPACE_DATA);
-	if (status & DOCG4_READ_ERROR) {
-		printf("docg4_read_page: bad status: 0x%02x\n", status);
-		writew(0, docptr + DOC_DATAEND);
-		return -EIO;
-	}
-
-	docg4_read_buf(mtd, buf, DOCG4_PAGE_SIZE); /* read the page data */
-
-	/* first 14 oob bytes read from I/O reg */
-	docg4_read_buf(mtd, nand->oob_poi, 14);
-
-	/* last 2 read from another reg */
-	buf16 = (uint16_t *)(nand->oob_poi + 14);
-	*buf16 = readw(docptr + DOCG4_MYSTERY_REG);
-
-	/*
-	 * Diskonchips read oob immediately after a page read.  Mtd
-	 * infrastructure issues a separate command for reading oob after the
-	 * page is read.  So we save the oob bytes in a local buffer and just
-	 * copy it if the next command reads oob from the same page.
-	 */
-	memcpy(doc->oob_buf, nand->oob_poi, 16);
-
-	write_nop(docptr);
-
-	if (likely(use_ecc)) {
-		/* read the register that tells us if bitflip(s) detected  */
-		edc_err = readw(docptr + DOC_ECCCONF1);
-		edc_err = readw(docptr + DOC_ECCCONF1);
-
-		/* If bitflips are reported, attempt to correct with ecc */
-		if (edc_err & DOC_ECCCONF1_BCH_SYNDROM_ERR) {
-			int bits_corrected = correct_data(mtd, buf, page);
-			if (bits_corrected == -EBADMSG)
-				mtd->ecc_stats.failed++;
-			else
-				mtd->ecc_stats.corrected += bits_corrected;
-		}
-	}
-
-	writew(0, docptr + DOC_DATAEND);
-	return 0;
-}
-
-
-static int docg4_read_page_raw(struct mtd_info *mtd, struct nand_chip *nand,
-			       uint8_t *buf, int oob_required, int page)
-{
-	return read_page(mtd, nand, buf, page, 0);
-}
-
-static int docg4_read_page(struct mtd_info *mtd, struct nand_chip *nand,
-			   uint8_t *buf, int oob_required, int page)
-{
-	return read_page(mtd, nand, buf, page, 1);
-}
-
-static int docg4_erase_block(struct mtd_info *mtd, int page)
-{
-	struct nand_chip *nand = mtd->priv;
-	struct docg4_priv *doc = nand->priv;
-	void __iomem *docptr = CONFIG_SYS_NAND_BASE;
-	uint16_t g4_page;
-
-	MTDDEBUG(MTD_DEBUG_LEVEL3, "%s: page %04x\n", __func__, page);
-
-	sequence_reset(docptr);
-
-	writew(DOCG4_SEQ_BLOCKERASE, docptr + DOC_FLASHSEQUENCE);
-	writew(DOC_CMD_PROG_BLOCK_ADDR, docptr + DOC_FLASHCOMMAND);
-	write_nop(docptr);
-
-	/* only 2 bytes of address are written to specify erase block */
-	g4_page = (uint16_t)(page / 4);  /* to g4's 2k page addressing */
-	writeb(g4_page & 0xff, docptr + DOC_FLASHADDRESS);
-	g4_page >>= 8;
-	writeb(g4_page & 0xff, docptr + DOC_FLASHADDRESS);
-	write_nop(docptr);
-
-	/* start the erasure */
-	writew(DOC_CMD_ERASECYCLE2, docptr + DOC_FLASHCOMMAND);
-	write_nop(docptr);
-	write_nop(docptr);
-
-	poll_status(docptr);
-	writew(DOCG4_SEQ_FLUSH, docptr + DOC_FLASHSEQUENCE);
-	writew(DOCG4_CMD_FLUSH, docptr + DOC_FLASHCOMMAND);
-	writew(DOC_ECCCONF0_READ_MODE | 4, docptr + DOC_ECCCONF0);
-	write_nop(docptr);
-	write_nop(docptr);
-	write_nop(docptr);
-	write_nop(docptr);
-	write_nop(docptr);
-
-	read_progstatus(doc, docptr);
-
-	writew(0, docptr + DOC_DATAEND);
-	write_nop(docptr);
-	poll_status(docptr);
-	write_nop(docptr);
-
-	return nand->waitfunc(mtd, nand);
-}
-
-static int read_factory_bbt(struct mtd_info *mtd)
-{
-	/*
-	 * The device contains a read-only factory bad block table.  Read it and
-	 * update the memory-based bbt accordingly.
-	 */
-
-	struct nand_chip *nand = mtd->priv;
-	uint32_t g4_addr = mtd_to_docg4_address(DOCG4_FACTORY_BBT_PAGE, 0);
-	uint8_t *buf;
-	int i, block, status;
-
-	buf = kzalloc(DOCG4_PAGE_SIZE, GFP_KERNEL);
-	if (buf == NULL)
-		return -ENOMEM;
-
-	read_page_prologue(CONFIG_SYS_NAND_BASE, g4_addr);
-	status = docg4_read_page(mtd, nand, buf, 0, DOCG4_FACTORY_BBT_PAGE);
-	if (status)
-		goto exit;
-
-	/*
-	 * If no memory-based bbt was created, exit.  This will happen if module
-	 * parameter ignore_badblocks is set.  Then why even call this function?
-	 * For an unknown reason, block erase always fails if it's the first
-	 * operation after device power-up.  The above read ensures it never is.
-	 * Ugly, I know.
-	 */
-	if (nand->bbt == NULL)  /* no memory-based bbt */
-		goto exit;
-
-	/*
-	 * Parse factory bbt and update memory-based bbt.  Factory bbt format is
-	 * simple: one bit per block, block numbers increase left to right (msb
-	 * to lsb).  Bit clear means bad block.
-	 */
-	for (i = block = 0; block < DOCG4_NUMBLOCKS; block += 8, i++) {
-		int bitnum;
-		uint8_t mask;
-		for (bitnum = 0, mask = 0x80;
-		     bitnum < 8; bitnum++, mask >>= 1) {
-			if (!(buf[i] & mask)) {
-				int badblock = block + bitnum;
-				nand->bbt[badblock / 4] |=
-					0x03 << ((badblock % 4) * 2);
-				mtd->ecc_stats.badblocks++;
-				printf("factory-marked bad block: %d\n",
-				       badblock);
-			}
-		}
-	}
- exit:
-	kfree(buf);
-	return status;
-}
-
-static int docg4_block_markbad(struct mtd_info *mtd, loff_t ofs)
-{
-	/*
-	 * Mark a block as bad.  Bad blocks are marked in the oob area of the
-	 * first page of the block.  The default scan_bbt() in the nand
-	 * infrastructure code works fine for building the memory-based bbt
-	 * during initialization, as does the nand infrastructure function that
-	 * checks if a block is bad by reading the bbt.  This function replaces
-	 * the nand default because writes to oob-only are not supported.
-	 */
-
-	int ret, i;
-	uint8_t *buf;
-	struct nand_chip *nand = mtd->priv;
-	struct nand_bbt_descr *bbtd = nand->badblock_pattern;
-	int block = (int)(ofs >> nand->bbt_erase_shift);
-	int page = (int)(ofs >> nand->page_shift);
-	uint32_t g4_addr = mtd_to_docg4_address(page, 0);
-
-	MTDDEBUG(MTD_DEBUG_LEVEL3, "%s: %08llx\n", __func__, ofs);
-
-	if (unlikely(ofs & (DOCG4_BLOCK_SIZE - 1)))
-		printf("%s: ofs %llx not start of block!\n",
-		       __func__, ofs);
-
-	/* allocate blank buffer for page data */
-	buf = kzalloc(DOCG4_PAGE_SIZE, GFP_KERNEL);
-	if (buf == NULL)
-		return -ENOMEM;
-
-	/* update bbt in memory */
-	nand->bbt[block / 4] |= 0x01 << ((block & 0x03) * 2);
-
-	/* write bit-wise negation of pattern to oob buffer */
-	memset(nand->oob_poi, 0xff, mtd->oobsize);
-	for (i = 0; i < bbtd->len; i++)
-		nand->oob_poi[bbtd->offs + i] = ~bbtd->pattern[i];
-
-	/* write first page of block */
-	write_page_prologue(CONFIG_SYS_NAND_BASE, g4_addr);
-	docg4_write_page(mtd, nand, buf, 1);
-	ret = pageprog(mtd);
-	if (!ret)
-		mtd->ecc_stats.badblocks++;
-
-	kfree(buf);
-
-	return ret;
-}
-
-static uint8_t docg4_read_byte(struct mtd_info *mtd)
-{
-	struct nand_chip *nand = mtd->priv;
-	struct docg4_priv *doc = nand->priv;
-
-	MTDDEBUG(MTD_DEBUG_LEVEL3, "%s\n", __func__);
-
-	if (doc->last_command.command == NAND_CMD_STATUS) {
-		int status;
-
-		/*
-		 * Previous nand command was status request, so nand
-		 * infrastructure code expects to read the status here.  If an
-		 * error occurred in a previous operation, report it.
-		 */
-		doc->last_command.command = 0;
-
-		if (doc->status) {
-			status = doc->status;
-			doc->status = 0;
-		}
-
-		/* why is NAND_STATUS_WP inverse logic?? */
-		else
-			status = NAND_STATUS_WP | NAND_STATUS_READY;
-
-		return status;
-	}
-
-	printf("unexpectd call to read_byte()\n");
-
-	return 0;
-}
-
-static int docg4_wait(struct mtd_info *mtd, struct nand_chip *nand)
-{
-	struct docg4_priv *doc = nand->priv;
-	int status = NAND_STATUS_WP;       /* inverse logic?? */
-	MTDDEBUG(MTD_DEBUG_LEVEL3, "%s...\n", __func__);
-
-	/* report any previously unreported error */
-	if (doc->status) {
-		status |= doc->status;
-		doc->status = 0;
-		return status;
-	}
-
-	status |= poll_status(CONFIG_SYS_NAND_BASE);
-	return status;
-}
-
-int docg4_nand_init(struct mtd_info *mtd, struct nand_chip *nand, int devnum)
-{
-	uint16_t id1, id2;
-	struct docg4_priv *docg4;
-	int retval;
-
-	docg4 = kzalloc(sizeof(*docg4), GFP_KERNEL);
-	if (!docg4)
-		return -1;
-
-	mtd->priv = nand;
-	nand->priv = docg4;
-
-	/* These must be initialized here because the docg4 is non-standard
-	 * and doesn't produce an id that the nand code can use to look up
-	 * these values (nand_scan_ident() not called).
-	 */
-	mtd->size = DOCG4_CHIP_SIZE;
-	mtd->name = "Msys_Diskonchip_G4";
-	mtd->writesize = DOCG4_PAGE_SIZE;
-	mtd->erasesize = DOCG4_BLOCK_SIZE;
-	mtd->oobsize = DOCG4_OOB_SIZE;
-
-	nand->IO_ADDR_R =
-		(void __iomem *)CONFIG_SYS_NAND_BASE + DOC_IOSPACE_DATA;
-	nand->IO_ADDR_W = nand->IO_ADDR_R;
-	nand->chipsize = DOCG4_CHIP_SIZE;
-	nand->chip_shift = DOCG4_CHIP_SHIFT;
-	nand->bbt_erase_shift = DOCG4_ERASE_SHIFT;
-	nand->phys_erase_shift = DOCG4_ERASE_SHIFT;
-	nand->chip_delay = 20;
-	nand->page_shift = DOCG4_PAGE_SHIFT;
-	nand->pagemask = 0x3ffff;
-	nand->badblockpos = NAND_LARGE_BADBLOCK_POS;
-	nand->badblockbits = 8;
-	nand->ecc.layout = &docg4_oobinfo;
-	nand->ecc.mode = NAND_ECC_HW_SYNDROME;
-	nand->ecc.size = DOCG4_PAGE_SIZE;
-	nand->ecc.prepad = 8;
-	nand->ecc.bytes	= 8;
-	nand->ecc.strength = DOCG4_T;
-	nand->options = NAND_BUSWIDTH_16 | NAND_NO_SUBPAGE_WRITE;
-	nand->controller = &nand->hwcontrol;
-
-	/* methods */
-	nand->cmdfunc = docg4_command;
-	nand->waitfunc = docg4_wait;
-	nand->select_chip = docg4_select_chip;
-	nand->read_byte = docg4_read_byte;
-	nand->block_markbad = docg4_block_markbad;
-	nand->read_buf = docg4_read_buf;
-	nand->write_buf = docg4_write_buf16;
-	nand->scan_bbt = nand_default_bbt;
-	nand->erase = docg4_erase_block;
-	nand->ecc.read_page = docg4_read_page;
-	nand->ecc.write_page = docg4_write_page;
-	nand->ecc.read_page_raw = docg4_read_page_raw;
-	nand->ecc.write_page_raw = docg4_write_page_raw;
-	nand->ecc.read_oob = docg4_read_oob;
-	nand->ecc.write_oob = docg4_write_oob;
-
-	/*
-	 * The way the nand infrastructure code is written, a memory-based bbt
-	 * is not created if NAND_SKIP_BBTSCAN is set.  With no memory bbt,
-	 * nand->block_bad() is used.  So when ignoring bad blocks, we skip the
-	 * scan and define a dummy block_bad() which always returns 0.
-	 */
-	if (ignore_badblocks) {
-		nand->options |= NAND_SKIP_BBTSCAN;
-		nand->block_bad	= docg4_block_neverbad;
-	}
-
-	reset(CONFIG_SYS_NAND_BASE);
-
-	/* check for presence of g4 chip by reading id registers */
-	id1 = readw(CONFIG_SYS_NAND_BASE + DOC_CHIPID);
-	id1 = readw(CONFIG_SYS_NAND_BASE + DOCG4_MYSTERY_REG);
-	id2 = readw(CONFIG_SYS_NAND_BASE + DOC_CHIPID_INV);
-	id2 = readw(CONFIG_SYS_NAND_BASE + DOCG4_MYSTERY_REG);
-	if (id1 != DOCG4_IDREG1_VALUE || id2 != DOCG4_IDREG2_VALUE)
-		return -1;
-
-	/* initialize bch algorithm */
-	docg4->bch = init_bch(DOCG4_M, DOCG4_T, DOCG4_PRIMITIVE_POLY);
-	if (docg4->bch == NULL)
-		return -1;
-
-	retval = nand_scan_tail(mtd);
-	if (retval)
-		return -1;
-
-	/*
-	 * Scan for bad blocks and create bbt here, then add the factory-marked
-	 * bad blocks to the bbt.
-	 */
-	nand->scan_bbt(mtd);
-	nand->options |= NAND_BBT_SCANNED;
-	retval = read_factory_bbt(mtd);
-	if (retval)
-		return -1;
-
-	retval = nand_register(devnum);
-	if (retval)
-		return -1;
-
-	return 0;
-}
diff --git a/drivers/mtd/nand/docg4_spl.c b/drivers/mtd/nand/docg4_spl.c
deleted file mode 100644
index 351b75a..0000000
--- a/drivers/mtd/nand/docg4_spl.c
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * SPL driver for Diskonchip G4 nand flash
- *
- * Copyright (C) 2013 Mike Dunn <mikedunn@newsguy.com>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- *
- * This driver basically mimics the load functionality of a typical IPL (initial
- * program loader) resident in the 2k NOR-like region of the docg4 that is
- * mapped to the reset vector.  It allows the u-boot SPL to continue loading if
- * the IPL loads a fixed number of flash blocks that is insufficient to contain
- * the entire u-boot image.  In this case, a concatenated spl + u-boot image is
- * written at the flash offset from which the IPL loads an image, and when the
- * IPL jumps to the SPL, the SPL resumes loading where the IPL left off.  See
- * the palmtreo680 for an example.
- *
- * This driver assumes that the data was written to the flash using the device's
- * "reliable" mode, and also assumes that each 512 byte page is stored
- * redundantly in the subsequent page.  This storage format is likely to be used
- * by all boards that boot from the docg4.  The format compensates for the lack
- * of ecc in the IPL.
- *
- * Reliable mode reduces the capacity of a block by half, and the redundant
- * pages reduce it by half again.  As a result, the normal 256k capacity of a
- * block is reduced to 64k for the purposes of the IPL/SPL.
- */
-
-#include <asm/io.h>
-#include <linux/mtd/docg4.h>
-
-/* forward declarations */
-static inline void write_nop(void __iomem *docptr);
-static int poll_status(void __iomem *docptr);
-static void write_addr(void __iomem *docptr, uint32_t docg4_addr);
-static void address_sequence(unsigned int g4_page, unsigned int g4_index,
-			     void __iomem *docptr);
-static int docg4_load_block_reliable(uint32_t flash_offset, void *dest_addr);
-
-int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst)
-{
-	void *load_addr = dst;
-	uint32_t flash_offset = offs;
-	const unsigned int block_count =
-		(size + DOCG4_BLOCK_CAPACITY_SPL - 1)
-		/ DOCG4_BLOCK_CAPACITY_SPL;
-	int i;
-
-	for (i = 0; i < block_count; i++) {
-		int ret = docg4_load_block_reliable(flash_offset, load_addr);
-		if (ret)
-			return ret;
-		load_addr += DOCG4_BLOCK_CAPACITY_SPL;
-		flash_offset += DOCG4_BLOCK_SIZE;
-	}
-	return 0;
-}
-
-static inline void write_nop(void __iomem *docptr)
-{
-	writew(0, docptr + DOC_NOP);
-}
-
-static int poll_status(void __iomem *docptr)
-{
-	/*
-	 * Busy-wait for the FLASHREADY bit to be set in the FLASHCONTROL
-	 * register.  Operations known to take a long time (e.g., block erase)
-	 * should sleep for a while before calling this.
-	 */
-
-	uint8_t flash_status;
-
-	/* hardware quirk requires reading twice initially */
-	flash_status = readb(docptr + DOC_FLASHCONTROL);
-
-	do {
-		flash_status = readb(docptr + DOC_FLASHCONTROL);
-	} while (!(flash_status & DOC_CTRL_FLASHREADY));
-
-	return 0;
-}
-
-static void write_addr(void __iomem *docptr, uint32_t docg4_addr)
-{
-	/* write the four address bytes packed in docg4_addr to the device */
-
-	writeb(docg4_addr & 0xff, docptr + DOC_FLASHADDRESS);
-	docg4_addr >>= 8;
-	writeb(docg4_addr & 0xff, docptr + DOC_FLASHADDRESS);
-	docg4_addr >>= 8;
-	writeb(docg4_addr & 0xff, docptr + DOC_FLASHADDRESS);
-	docg4_addr >>= 8;
-	writeb(docg4_addr & 0xff, docptr + DOC_FLASHADDRESS);
-}
-
-static void address_sequence(unsigned int g4_page, unsigned int g4_index,
-			     void __iomem *docptr)
-{
-	writew(DOCG4_SEQ_PAGE_READ, docptr + DOC_FLASHSEQUENCE);
-	writew(DOCG4_CMD_PAGE_READ, docptr + DOC_FLASHCOMMAND);
-	write_nop(docptr);
-	write_addr(docptr, ((uint32_t)g4_page << 16) | g4_index);
-	write_nop(docptr);
-}
-
-static int docg4_load_block_reliable(uint32_t flash_offset, void *dest_addr)
-{
-	void __iomem *docptr = (void *)CONFIG_SYS_NAND_BASE;
-	unsigned int g4_page = flash_offset >> 11; /* 2k page */
-	const unsigned int last_g4_page = g4_page + 0x80; /* last in block */
-	int g4_index = 0;
-	uint16_t flash_status;
-	uint16_t *buf;
-
-	/* flash_offset must be aligned to the start of a block */
-	if (flash_offset & 0x3ffff)
-		return -1;
-
-	writew(DOC_SEQ_RESET, docptr + DOC_FLASHSEQUENCE);
-	writew(DOC_CMD_RESET, docptr + DOC_FLASHCOMMAND);
-	write_nop(docptr);
-	write_nop(docptr);
-	poll_status(docptr);
-	write_nop(docptr);
-	writew(0x45, docptr + DOC_FLASHSEQUENCE);
-	writew(0xa3, docptr + DOC_FLASHCOMMAND);
-	write_nop(docptr);
-	writew(0x22, docptr + DOC_FLASHCOMMAND);
-	write_nop(docptr);
-
-	/* read 1st 4 oob bytes of first subpage of block */
-	address_sequence(g4_page, 0x0100, docptr); /* index at oob */
-	write_nop(docptr);
-	flash_status = readw(docptr + DOC_FLASHCONTROL);
-	flash_status = readw(docptr + DOC_FLASHCONTROL);
-	if (flash_status & 0x06) /* sequence or protection errors */
-		return -1;
-	writew(DOCG4_CMD_READ2, docptr + DOC_FLASHCOMMAND);
-	write_nop(docptr);
-	write_nop(docptr);
-	poll_status(docptr);
-	writew(DOC_ECCCONF0_READ_MODE | 4, docptr + DOC_ECCCONF0);
-	write_nop(docptr);
-	write_nop(docptr);
-	write_nop(docptr);
-	write_nop(docptr);
-	write_nop(docptr);
-
-	/*
-	 * Here we read the first four oob bytes of the first page of the block.
-	 * The IPL on the palmtreo680 requires that this contain a 32 bit magic
-	 * number, or the load aborts.  We'll ignore it.
-	 */
-	readw(docptr + 0x103c); /* hw quirk; 1st read discarded */
-	readw(docptr + 0x103c);	/* lower 16 bits of magic number */
-	readw(docptr + DOCG4_MYSTERY_REG); /* upper 16 bits of magic number */
-	writew(0, docptr + DOC_DATAEND);
-	write_nop(docptr);
-	write_nop(docptr);
-
-	/* load contents of block to memory */
-	buf = (uint16_t *)dest_addr;
-	do {
-		int i;
-
-		address_sequence(g4_page, g4_index, docptr);
-		writew(DOCG4_CMD_READ2,
-		       docptr + DOC_FLASHCOMMAND);
-		write_nop(docptr);
-		write_nop(docptr);
-		poll_status(docptr);
-		writew(DOC_ECCCONF0_READ_MODE |
-		       DOC_ECCCONF0_ECC_ENABLE |
-		       DOCG4_BCH_SIZE,
-		       docptr + DOC_ECCCONF0);
-		write_nop(docptr);
-		write_nop(docptr);
-		write_nop(docptr);
-		write_nop(docptr);
-		write_nop(docptr);
-
-		/* read the 512 bytes of page data, 2 bytes at a time */
-		readw(docptr + 0x103c); /* hw quirk */
-		for (i = 0; i < 256; i++)
-			*buf++ = readw(docptr + 0x103c);
-
-		/* read oob, but discard it */
-		for (i = 0; i < 7; i++)
-			readw(docptr + 0x103c);
-		readw(docptr + DOCG4_OOB_6_7);
-		readw(docptr + DOCG4_OOB_6_7);
-
-		writew(0, docptr + DOC_DATAEND);
-		write_nop(docptr);
-		write_nop(docptr);
-
-		if (!(g4_index & 0x100)) {
-			/* not redundant subpage read; check for ecc error */
-			write_nop(docptr);
-			flash_status = readw(docptr + DOC_ECCCONF1);
-			flash_status = readw(docptr + DOC_ECCCONF1);
-			if (flash_status & 0x80) { /* ecc error */
-				g4_index += 0x108; /* read redundant subpage */
-				buf -= 256;        /* back up ram ptr */
-				continue;
-			} else                       /* no ecc error */
-				g4_index += 0x210; /* skip redundant subpage */
-		} else  /* redundant page was just read; skip ecc error check */
-			g4_index += 0x108;
-
-		if (g4_index == 0x420) { /* finished with 2k page */
-			g4_index = 0;
-			g4_page += 2; /* odd-numbered 2k pages skipped */
-		}
-
-	} while (g4_page != last_g4_page); /* while still on same block */
-
-	return 0;
-}
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index d457d53..f621f14 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -154,8 +154,8 @@
  */
 static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
 {
-	struct nand_chip *chip = mtd->priv;
-	struct fsl_elbc_mtd *priv = chip->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
 	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
 	fsl_lbc_t *lbc = ctrl->regs;
 	int buf_num;
@@ -194,8 +194,8 @@
  */
 static int fsl_elbc_run_command(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd->priv;
-	struct fsl_elbc_mtd *priv = chip->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
 	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
 	fsl_lbc_t *lbc = ctrl->regs;
 	u32 timeo = (CONFIG_SYS_HZ * 10) / 1000;
@@ -246,7 +246,7 @@
 
 static void fsl_elbc_do_read(struct nand_chip *chip, int oob)
 {
-	struct fsl_elbc_mtd *priv = chip->priv;
+	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
 	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
 	fsl_lbc_t *lbc = ctrl->regs;
 
@@ -279,8 +279,8 @@
 static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 			     int column, int page_addr)
 {
-	struct nand_chip *chip = mtd->priv;
-	struct fsl_elbc_mtd *priv = chip->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
 	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
 	fsl_lbc_t *lbc = ctrl->regs;
 
@@ -489,8 +489,8 @@
  */
 static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
 {
-	struct nand_chip *chip = mtd->priv;
-	struct fsl_elbc_mtd *priv = chip->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
 	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
 	unsigned int bufsize = mtd->writesize + mtd->oobsize;
 
@@ -526,8 +526,8 @@
  */
 static u8 fsl_elbc_read_byte(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd->priv;
-	struct fsl_elbc_mtd *priv = chip->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
 	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
 
 	/* If there are still bytes in the FCM, then use the next byte. */
@@ -543,8 +543,8 @@
  */
 static void fsl_elbc_read_buf(struct mtd_info *mtd, u8 *buf, int len)
 {
-	struct nand_chip *chip = mtd->priv;
-	struct fsl_elbc_mtd *priv = chip->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
 	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
 	int avail;
 
@@ -566,7 +566,7 @@
  */
 static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip)
 {
-	struct fsl_elbc_mtd *priv = chip->priv;
+	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
 	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
 	fsl_lbc_t *lbc = ctrl->regs;
 
@@ -611,7 +611,8 @@
  * waitfunc.
  */
 static int fsl_elbc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
-				const uint8_t *buf, int oob_required)
+				const uint8_t *buf, int oob_required,
+				int page)
 {
 	fsl_elbc_write_buf(mtd, buf, mtd->writesize);
 	fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
@@ -626,7 +627,7 @@
  */
 static int fsl_elbc_write_subpage(struct mtd_info *mtd, struct nand_chip *chip,
 				uint32_t offset, uint32_t data_len,
-				const uint8_t *buf, int oob_required)
+				const uint8_t *buf, int oob_required, int page)
 {
 	fsl_elbc_write_buf(mtd, buf, mtd->writesize);
 	fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
@@ -656,7 +657,7 @@
 
 static int fsl_elbc_chip_init(int devnum, u8 *addr)
 {
-	struct mtd_info *mtd = &nand_info[devnum];
+	struct mtd_info *mtd;
 	struct nand_chip *nand;
 	struct fsl_elbc_mtd *priv;
 	uint32_t br = 0, or = 0;
@@ -697,7 +698,7 @@
 	}
 
 	nand = &priv->chip;
-	mtd->priv = nand;
+	mtd = nand_to_mtd(nand);
 
 	elbc_ctrl->chips[priv->bank] = priv;
 
@@ -719,7 +720,7 @@
 	nand->bbt_options = NAND_BBT_USE_FLASH;
 
 	nand->controller = &elbc_ctrl->controller;
-	nand->priv = priv;
+	nand_set_controller_data(nand, priv);
 
 	nand->ecc.read_page = fsl_elbc_read_page;
 	nand->ecc.write_page = fsl_elbc_write_page;
@@ -787,7 +788,7 @@
 	if (ret)
 		return ret;
 
-	ret = nand_register(devnum);
+	ret = nand_register(devnum, mtd);
 	if (ret)
 		return ret;
 
diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c
index 975b0d4..7001cbd 100644
--- a/drivers/mtd/nand/fsl_ifc_nand.c
+++ b/drivers/mtd/nand/fsl_ifc_nand.c
@@ -222,8 +222,8 @@
  */
 static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
 {
-	struct nand_chip *chip = mtd->priv;
-	struct fsl_ifc_mtd *priv = chip->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
 	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
 	struct fsl_ifc_runtime *ifc = ctrl->regs.rregs;
 	int buf_num;
@@ -247,8 +247,8 @@
 static int is_blank(struct mtd_info *mtd, struct fsl_ifc_ctrl *ctrl,
 		    unsigned int bufnum)
 {
-	struct nand_chip *chip = mtd->priv;
-	struct fsl_ifc_mtd *priv = chip->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
 	u8 __iomem *addr = priv->vbase + bufnum * (mtd->writesize * 2);
 	u32 __iomem *main = (u32 *)addr;
 	u8 __iomem *oob = addr + mtd->writesize;
@@ -286,8 +286,8 @@
  */
 static int fsl_ifc_run_command(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd->priv;
-	struct fsl_ifc_mtd *priv = chip->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
 	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
 	struct fsl_ifc_runtime *ifc = ctrl->regs.rregs;
 	u32 timeo = (CONFIG_SYS_HZ * 10) / 1000;
@@ -367,7 +367,7 @@
 			    int oob,
 			    struct mtd_info *mtd)
 {
-	struct fsl_ifc_mtd *priv = chip->priv;
+	struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
 	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
 	struct fsl_ifc_runtime *ifc = ctrl->regs.rregs;
 
@@ -404,8 +404,8 @@
 static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 			     int column, int page_addr)
 {
-	struct nand_chip *chip = mtd->priv;
-	struct fsl_ifc_mtd *priv = chip->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
 	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
 	struct fsl_ifc_runtime *ifc = ctrl->regs.rregs;
 
@@ -607,8 +607,8 @@
  */
 static void fsl_ifc_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
 {
-	struct nand_chip *chip = mtd->priv;
-	struct fsl_ifc_mtd *priv = chip->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
 	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
 	unsigned int bufsize = mtd->writesize + mtd->oobsize;
 
@@ -635,8 +635,8 @@
  */
 static u8 fsl_ifc_read_byte(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd->priv;
-	struct fsl_ifc_mtd *priv = chip->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
 	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
 	unsigned int offset;
 
@@ -659,8 +659,8 @@
  */
 static uint8_t fsl_ifc_read_byte16(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd->priv;
-	struct fsl_ifc_mtd *priv = chip->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
 	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
 	uint16_t data;
 
@@ -683,8 +683,8 @@
  */
 static void fsl_ifc_read_buf(struct mtd_info *mtd, u8 *buf, int len)
 {
-	struct nand_chip *chip = mtd->priv;
-	struct fsl_ifc_mtd *priv = chip->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
 	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
 	int avail;
 
@@ -706,7 +706,7 @@
  */
 static int fsl_ifc_wait(struct mtd_info *mtd, struct nand_chip *chip)
 {
-	struct fsl_ifc_mtd *priv = chip->priv;
+	struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
 	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
 	struct fsl_ifc_runtime *ifc = ctrl->regs.rregs;
 	u32 nand_fsr;
@@ -739,7 +739,7 @@
 static int fsl_ifc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
 			     uint8_t *buf, int oob_required, int page)
 {
-	struct fsl_ifc_mtd *priv = chip->priv;
+	struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
 	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
 
 	fsl_ifc_read_buf(mtd, buf, mtd->writesize);
@@ -755,7 +755,7 @@
  * waitfunc.
  */
 static int fsl_ifc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
-			       const uint8_t *buf, int oob_required)
+			       const uint8_t *buf, int oob_required, int page)
 {
 	fsl_ifc_write_buf(mtd, buf, mtd->writesize);
 	fsl_ifc_write_buf(mtd, chip->oob_poi, mtd->oobsize);
@@ -880,7 +880,7 @@
 
 static int fsl_ifc_chip_init(int devnum, u8 *addr)
 {
-	struct mtd_info *mtd = &nand_info[devnum];
+	struct mtd_info *mtd;
 	struct nand_chip *nand;
 	struct fsl_ifc_mtd *priv;
 	struct nand_ecclayout *layout;
@@ -925,7 +925,7 @@
 	}
 
 	nand = &priv->chip;
-	mtd->priv = nand;
+	mtd = nand_to_mtd(nand);
 
 	ifc_ctrl->chips[priv->bank] = priv;
 
@@ -954,7 +954,7 @@
 	}
 
 	nand->controller = &ifc_ctrl->controller;
-	nand->priv = priv;
+	nand_set_controller_data(nand, priv);
 
 	nand->ecc.read_page = fsl_ifc_read_page;
 	nand->ecc.write_page = fsl_ifc_write_page;
@@ -1044,7 +1044,7 @@
 	if (ret)
 		return ret;
 
-	ret = nand_register(devnum);
+	ret = nand_register(devnum, mtd);
 	if (ret)
 		return ret;
 	return 0;
diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c
index 5426c32..d2b3881 100644
--- a/drivers/mtd/nand/fsl_upm.c
+++ b/drivers/mtd/nand/fsl_upm.c
@@ -64,8 +64,8 @@
 #if CONFIG_SYS_NAND_MAX_CHIPS > 1
 static void fun_select_chip(struct mtd_info *mtd, int chip_nr)
 {
-	struct nand_chip *chip = mtd->priv;
-	struct fsl_upm_nand *fun = chip->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct fsl_upm_nand *fun = nand_get_controller_data(chip);
 
 	if (chip_nr >= 0) {
 		fun->chip_nr = chip_nr;
@@ -79,8 +79,8 @@
 
 static void fun_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 {
-	struct nand_chip *chip = mtd->priv;
-	struct fsl_upm_nand *fun = chip->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct fsl_upm_nand *fun = nand_get_controller_data(chip);
 	void __iomem *io_addr;
 	u32 mar;
 
@@ -123,7 +123,7 @@
 
 static u8 upm_nand_read_byte(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 
 	return in_8(chip->IO_ADDR_R);
 }
@@ -131,8 +131,8 @@
 static void upm_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
 {
 	int i;
-	struct nand_chip *chip = mtd->priv;
-	struct fsl_upm_nand *fun = chip->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct fsl_upm_nand *fun = nand_get_controller_data(chip);
 
 	for (i = 0; i < len; i++) {
 		out_8(chip->IO_ADDR_W, buf[i]);
@@ -147,7 +147,7 @@
 static void upm_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
 {
 	int i;
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 
 	for (i = 0; i < len; i++)
 		buf[i] = in_8(chip->IO_ADDR_R);
@@ -155,8 +155,8 @@
 
 static int nand_dev_ready(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd->priv;
-	struct fsl_upm_nand *fun = chip->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct fsl_upm_nand *fun = nand_get_controller_data(chip);
 
 	return fun->dev_ready(fun->chip_nr);
 }
@@ -168,7 +168,7 @@
 
 	fun->last_ctrl = NAND_CLE;
 
-	chip->priv = fun;
+	nand_set_controller_data(chip, fun);
 	chip->chip_delay = fun->chip_delay;
 	chip->ecc.mode = NAND_ECC_SOFT;
 	chip->cmd_ctrl = fun_cmd_ctrl;
diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c
index e0e9e1e..a1f2cba 100644
--- a/drivers/mtd/nand/fsmc_nand.c
+++ b/drivers/mtd/nand/fsmc_nand.c
@@ -165,7 +165,7 @@
 
 static void fsmc_nand_hwcontrol(struct mtd_info *mtd, int cmd, uint ctrl)
 {
-	struct nand_chip *this = mtd->priv;
+	struct nand_chip *this = mtd_to_nand(mtd);
 	ulong IO_ADDR_W;
 
 	if (ctrl & NAND_CTRL_CHANGE) {
@@ -409,8 +409,8 @@
 	 * 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];
-	nand = mtd->priv;
+	mtd = nand_info[nand_curr_device];
+	nand = mtd_to_nand(mtd);
 
 	/* Setup the ecc configurations again */
 	if (eccstrength == 1) {
@@ -443,7 +443,6 @@
 {
 	static int chip_nr;
 	struct mtd_info *mtd;
-	int i;
 	u32 peripid2 = readl(&fsmc_regs_p->peripid2);
 
 	fsmc_version = (peripid2 >> FSMC_REVISION_SHFT) &
@@ -480,8 +479,7 @@
 		(void  __iomem *)CONFIG_SYS_NAND_BASE;
 	nand->badblockbits = 7;
 
-	mtd = &nand_info[chip_nr++];
-	mtd->priv = nand;
+	mtd = nand_to_mtd(nand);
 
 	switch (fsmc_version) {
 	case FSMC_VER8:
@@ -514,9 +512,8 @@
 	if (nand_scan_tail(mtd))
 		return -ENXIO;
 
-	for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
-		if (nand_register(i))
-			return -ENXIO;
+	if (nand_register(chip_nr++, mtd))
+		return -ENXIO;
 
 	return 0;
 }
diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c
deleted file mode 100644
index abcedc2..0000000
--- a/drivers/mtd/nand/jz4740_nand.c
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- * Platform independend driver for JZ4740.
- *
- * Copyright (c) 2007 Ingenic Semiconductor Inc.
- * Author: <jlwei@ingenic.cn>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-#include <common.h>
-
-#include <nand.h>
-#include <asm/io.h>
-#include <asm/jz4740.h>
-
-#define JZ_NAND_DATA_ADDR ((void __iomem *)0xB8000000)
-#define JZ_NAND_CMD_ADDR (JZ_NAND_DATA_ADDR + 0x8000)
-#define JZ_NAND_ADDR_ADDR (JZ_NAND_DATA_ADDR + 0x10000)
-
-#define JZ_NAND_ECC_CTRL_ENCODING	BIT(3)
-#define JZ_NAND_ECC_CTRL_RS		BIT(2)
-#define JZ_NAND_ECC_CTRL_RESET		BIT(1)
-#define JZ_NAND_ECC_CTRL_ENABLE		BIT(0)
-
-#define EMC_SMCR1_OPT_NAND	0x094c4400
-/* Optimize the timing of nand */
-
-static struct jz4740_emc * emc = (struct jz4740_emc *)JZ4740_EMC_BASE;
-
-static struct nand_ecclayout qi_lb60_ecclayout_2gb = {
-	.eccbytes = 72,
-	.eccpos = {
-		12, 13, 14, 15, 16, 17, 18, 19,
-		20, 21, 22, 23, 24, 25, 26, 27,
-		28, 29, 30, 31, 32, 33, 34, 35,
-		36, 37, 38, 39, 40, 41, 42, 43,
-		44, 45, 46, 47, 48, 49, 50, 51,
-		52, 53, 54, 55, 56, 57, 58, 59,
-		60, 61, 62, 63, 64, 65, 66, 67,
-		68, 69, 70, 71, 72, 73, 74, 75,
-		76, 77, 78, 79, 80, 81, 82, 83 },
-	.oobfree = {
-		{.offset = 2,
-		 .length = 10 },
-		{.offset = 84,
-		 .length = 44 } }
-};
-
-static int is_reading;
-
-static void jz_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
-{
-	struct nand_chip *this = mtd->priv;
-	uint32_t reg;
-
-	if (ctrl & NAND_CTRL_CHANGE) {
-		if (ctrl & NAND_ALE)
-			this->IO_ADDR_W = JZ_NAND_ADDR_ADDR;
-		else if (ctrl & NAND_CLE)
-			this->IO_ADDR_W = JZ_NAND_CMD_ADDR;
-		else
-			this->IO_ADDR_W = JZ_NAND_DATA_ADDR;
-
-		reg = readl(&emc->nfcsr);
-		if (ctrl & NAND_NCE)
-			reg |= EMC_NFCSR_NFCE1;
-		else
-			reg &= ~EMC_NFCSR_NFCE1;
-		writel(reg, &emc->nfcsr);
-	}
-
-	if (cmd != NAND_CMD_NONE)
-		writeb(cmd, this->IO_ADDR_W);
-}
-
-static int jz_nand_device_ready(struct mtd_info *mtd)
-{
-	return (readl(GPIO_PXPIN(2)) & 0x40000000) ? 1 : 0;
-}
-
-void board_nand_select_device(struct nand_chip *nand, int chip)
-{
-	/*
-	 * Don't use "chip" to address the NAND device,
-	 * generate the cs from the address where it is encoded.
-	 */
-}
-
-static int jz_nand_rs_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
-				u_char *ecc_code)
-{
-	uint32_t status;
-	int i;
-
-	if (is_reading)
-		return 0;
-
-	do {
-		status = readl(&emc->nfints);
-	} while (!(status & EMC_NFINTS_ENCF));
-
-	/* disable ecc */
-	writel(readl(&emc->nfecr) & ~EMC_NFECR_ECCE, &emc->nfecr);
-
-	for (i = 0; i < 9; i++)
-		ecc_code[i] = readb(&emc->nfpar[i]);
-
-	return 0;
-}
-
-static void jz_nand_hwctl(struct mtd_info *mtd, int mode)
-{
-	uint32_t reg;
-
-	writel(0, &emc->nfints);
-	reg = readl(&emc->nfecr);
-	reg |= JZ_NAND_ECC_CTRL_RESET;
-	reg |= JZ_NAND_ECC_CTRL_ENABLE;
-	reg |= JZ_NAND_ECC_CTRL_RS;
-
-	switch (mode) {
-	case NAND_ECC_READ:
-		reg &= ~JZ_NAND_ECC_CTRL_ENCODING;
-		is_reading = 1;
-		break;
-	case NAND_ECC_WRITE:
-		reg |= JZ_NAND_ECC_CTRL_ENCODING;
-		is_reading = 0;
-		break;
-	default:
-		break;
-	}
-
-	writel(reg, &emc->nfecr);
-}
-
-/* Correct 1~9-bit errors in 512-bytes data */
-static void jz_rs_correct(unsigned char *dat, int idx, int mask)
-{
-	int i;
-
-	idx--;
-
-	i = idx + (idx >> 3);
-	if (i >= 512)
-		return;
-
-	mask <<= (idx & 0x7);
-
-	dat[i] ^= mask & 0xff;
-	if (i < 511)
-		dat[i + 1] ^= (mask >> 8) & 0xff;
-}
-
-static int jz_nand_rs_correct_data(struct mtd_info *mtd, u_char *dat,
-				   u_char *read_ecc, u_char *calc_ecc)
-{
-	int k;
-	uint32_t errcnt, index, mask, status;
-
-	/* Set PAR values */
-	const uint8_t all_ff_ecc[] = {
-		0xcd, 0x9d, 0x90, 0x58, 0xf4, 0x8b, 0xff, 0xb7, 0x6f };
-
-	if (read_ecc[0] == 0xff && read_ecc[1] == 0xff &&
-	    read_ecc[2] == 0xff && read_ecc[3] == 0xff &&
-	    read_ecc[4] == 0xff && read_ecc[5] == 0xff &&
-	    read_ecc[6] == 0xff && read_ecc[7] == 0xff &&
-	    read_ecc[8] == 0xff) {
-		for (k = 0; k < 9; k++)
-			writeb(all_ff_ecc[k], &emc->nfpar[k]);
-	} else {
-		for (k = 0; k < 9; k++)
-			writeb(read_ecc[k], &emc->nfpar[k]);
-	}
-	/* Set PRDY */
-	writel(readl(&emc->nfecr) | EMC_NFECR_PRDY, &emc->nfecr);
-
-	/* Wait for completion */
-	do {
-		status = readl(&emc->nfints);
-	} while (!(status & EMC_NFINTS_DECF));
-
-	/* disable ecc */
-	writel(readl(&emc->nfecr) & ~EMC_NFECR_ECCE, &emc->nfecr);
-
-	/* Check decoding */
-	if (!(status & EMC_NFINTS_ERR))
-		return 0;
-
-	if (status & EMC_NFINTS_UNCOR) {
-		printf("uncorrectable ecc\n");
-		return -1;
-	}
-
-	errcnt = (status & EMC_NFINTS_ERRCNT_MASK) >> EMC_NFINTS_ERRCNT_BIT;
-
-	switch (errcnt) {
-	case 4:
-		index = (readl(&emc->nferr[3]) & EMC_NFERR_INDEX_MASK) >>
-			EMC_NFERR_INDEX_BIT;
-		mask = (readl(&emc->nferr[3]) & EMC_NFERR_MASK_MASK) >>
-			EMC_NFERR_MASK_BIT;
-		jz_rs_correct(dat, index, mask);
-	case 3:
-		index = (readl(&emc->nferr[2]) & EMC_NFERR_INDEX_MASK) >>
-			EMC_NFERR_INDEX_BIT;
-		mask = (readl(&emc->nferr[2]) & EMC_NFERR_MASK_MASK) >>
-			EMC_NFERR_MASK_BIT;
-		jz_rs_correct(dat, index, mask);
-	case 2:
-		index = (readl(&emc->nferr[1]) & EMC_NFERR_INDEX_MASK) >>
-			EMC_NFERR_INDEX_BIT;
-		mask = (readl(&emc->nferr[1]) & EMC_NFERR_MASK_MASK) >>
-			EMC_NFERR_MASK_BIT;
-		jz_rs_correct(dat, index, mask);
-	case 1:
-		index = (readl(&emc->nferr[0]) & EMC_NFERR_INDEX_MASK) >>
-			EMC_NFERR_INDEX_BIT;
-		mask = (readl(&emc->nferr[0]) & EMC_NFERR_MASK_MASK) >>
-			EMC_NFERR_MASK_BIT;
-		jz_rs_correct(dat, index, mask);
-	default:
-		break;
-	}
-
-	return errcnt;
-}
-
-/*
- * Main initialization routine
- */
-int board_nand_init(struct nand_chip *nand)
-{
-	uint32_t reg;
-
-	reg = readl(&emc->nfcsr);
-	reg |= EMC_NFCSR_NFE1;	/* EMC setup, Set NFE bit */
-	writel(reg, &emc->nfcsr);
-
-	writel(EMC_SMCR1_OPT_NAND, &emc->smcr[1]);
-
-	nand->IO_ADDR_R		= JZ_NAND_DATA_ADDR;
-	nand->IO_ADDR_W		= JZ_NAND_DATA_ADDR;
-	nand->cmd_ctrl		= jz_nand_cmd_ctrl;
-	nand->dev_ready		= jz_nand_device_ready;
-	nand->ecc.hwctl		= jz_nand_hwctl;
-	nand->ecc.correct	= jz_nand_rs_correct_data;
-	nand->ecc.calculate	= jz_nand_rs_calculate_ecc;
-	nand->ecc.mode		= NAND_ECC_HW_OOB_FIRST;
-	nand->ecc.size		= CONFIG_SYS_NAND_ECCSIZE;
-	nand->ecc.bytes		= CONFIG_SYS_NAND_ECCBYTES;
-	nand->ecc.strength	= 4;
-	nand->ecc.layout	= &qi_lb60_ecclayout_2gb;
-	nand->chip_delay	= 50;
-	nand->bbt_options	|= NAND_BBT_USE_FLASH;
-
-	return 0;
-}
diff --git a/drivers/mtd/nand/kb9202_nand.c b/drivers/mtd/nand/kb9202_nand.c
index 22c5625..e978cf8 100644
--- a/drivers/mtd/nand/kb9202_nand.c
+++ b/drivers/mtd/nand/kb9202_nand.c
@@ -35,7 +35,7 @@
  */
 static void kb9202_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 {
-	struct nand_chip *this = mtd->priv;
+	struct nand_chip *this = mtd_to_nand(mtd);
 
 	if (ctrl & NAND_CTRL_CHANGE) {
 		ulong IO_ADDR_W = (ulong) this->IO_ADDR_W;
diff --git a/drivers/mtd/nand/kirkwood_nand.c b/drivers/mtd/nand/kirkwood_nand.c
index d734113..d0a68bd 100644
--- a/drivers/mtd/nand/kirkwood_nand.c
+++ b/drivers/mtd/nand/kirkwood_nand.c
@@ -33,7 +33,7 @@
 static void kw_nand_hwcontrol(struct mtd_info *mtd, int cmd,
 			      unsigned int ctrl)
 {
-	struct nand_chip *nc = mtd->priv;
+	struct nand_chip *nc = mtd_to_nand(mtd);
 	u32 offs;
 
 	if (cmd == NAND_CMD_NONE)
diff --git a/drivers/mtd/nand/lpc32xx_nand_mlc.c b/drivers/mtd/nand/lpc32xx_nand_mlc.c
index 8156fe9..4262029 100644
--- a/drivers/mtd/nand/lpc32xx_nand_mlc.c
+++ b/drivers/mtd/nand/lpc32xx_nand_mlc.c
@@ -378,7 +378,8 @@
  */
 
 static int lpc32xx_write_page_hwecc(struct mtd_info *mtd,
-	struct nand_chip *chip, const uint8_t *buf, int oob_required)
+	struct nand_chip *chip, const uint8_t *buf, int oob_required,
+	int page)
 {
 	unsigned int i, status, timeout;
 	struct lpc32xx_oob *oob = (struct lpc32xx_oob *)chip->oob_poi;
@@ -435,7 +436,8 @@
  */
 
 static int lpc32xx_write_page_raw(struct mtd_info *mtd,
-	struct nand_chip *chip, const uint8_t *buf, int oob_required)
+	struct nand_chip *chip, const uint8_t *buf, int oob_required,
+	int page)
 {
 	unsigned int i;
 	struct lpc32xx_oob *oob = (struct lpc32xx_oob *)chip->oob_poi;
@@ -539,11 +541,7 @@
 
 void board_nand_init(void)
 {
-	/* we have only one device anyway */
-	struct mtd_info *mtd = &nand_info[0];
-	/* chip is struct nand_chip, and is now provided by the driver. */
-	mtd->priv = &lpc32xx_chip;
-	/* to store return status in case we need to print it */
+	struct mtd_info *mtd = &lpc32xx_chip.mtd;
 	int ret;
 
 	/* Set all BOARDSPECIFIC (actually core-specific) fields  */
@@ -597,7 +595,7 @@
 	}
 
 	/* chip is good, register it */
-	ret = nand_register(0);
+	ret = nand_register(0, mtd);
 	if (ret)
 		error("nand_register returned %i", ret);
 }
diff --git a/drivers/mtd/nand/lpc32xx_nand_slc.c b/drivers/mtd/nand/lpc32xx_nand_slc.c
index 4e1be36..daa1e7a 100644
--- a/drivers/mtd/nand/lpc32xx_nand_slc.c
+++ b/drivers/mtd/nand/lpc32xx_nand_slc.c
@@ -291,7 +291,7 @@
 static void lpc32xx_nand_xfer(struct mtd_info *mtd, const u8 *buf,
 			      int len, int read)
 {
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 	u32 config;
 	int ret;
 
@@ -486,7 +486,8 @@
 /* Reuse the logic from "nand_write_page_hwecc()" */
 static int lpc32xx_write_page_hwecc(struct mtd_info *mtd,
 				    struct nand_chip *chip,
-				    const uint8_t *buf, int oob_required)
+				    const uint8_t *buf, int oob_required,
+				    int page)
 {
 	int i;
 	uint8_t *ecc_calc = chip->buffers->ecccalc;
diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c
index e621c36..8a8775c 100644
--- a/drivers/mtd/nand/mpc5121_nfc.c
+++ b/drivers/mtd/nand/mpc5121_nfc.c
@@ -100,7 +100,6 @@
 #define NFC_WPC_UNLOCK		(1 << 2)
 
 struct mpc5121_nfc_prv {
-	struct mtd_info mtd;
 	struct nand_chip chip;
 	int irq;
 	void __iomem *regs;
@@ -117,8 +116,8 @@
 /* Read NFC register */
 static inline u16 nfc_read(struct mtd_info *mtd, uint reg)
 {
-	struct nand_chip *chip = mtd->priv;
-	struct mpc5121_nfc_prv *prv = chip->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct mpc5121_nfc_prv *prv = nand_get_controller_data(chip);
 
 	return in_be16(prv->regs + reg);
 }
@@ -126,8 +125,8 @@
 /* Write NFC register */
 static inline void nfc_write(struct mtd_info *mtd, uint reg, u16 val)
 {
-	struct nand_chip *chip = mtd->priv;
-	struct mpc5121_nfc_prv *prv = chip->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct mpc5121_nfc_prv *prv = nand_get_controller_data(chip);
 
 	out_be16(prv->regs + reg, val);
 }
@@ -211,7 +210,7 @@
 /* Do address cycle(s) */
 static void mpc5121_nfc_addr_cycle(struct mtd_info *mtd, int column, int page)
 {
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 	u32 pagemask = chip->pagemask;
 
 	if (column != -1) {
@@ -283,8 +282,8 @@
 static void mpc5121_nfc_command(struct mtd_info *mtd, unsigned command,
 				int column, int page)
 {
-	struct nand_chip *chip = mtd->priv;
-	struct mpc5121_nfc_prv *prv = chip->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct mpc5121_nfc_prv *prv = nand_get_controller_data(chip);
 
 	prv->column = (column >= 0) ? column : 0;
 	prv->spareonly = 0;
@@ -357,8 +356,8 @@
 static void mpc5121_nfc_copy_spare(struct mtd_info *mtd, uint offset,
 				   u8 * buffer, uint size, int wr)
 {
-	struct nand_chip *nand = mtd->priv;
-	struct mpc5121_nfc_prv *prv = nand->priv;
+	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct mpc5121_nfc_prv *prv = nand_get_controller_data(nand);
 	uint o, s, sbsize, blksize;
 
 	/*
@@ -410,8 +409,8 @@
 static void mpc5121_nfc_buf_copy(struct mtd_info *mtd, u_char * buf, int len,
 				 int wr)
 {
-	struct nand_chip *chip = mtd->priv;
-	struct mpc5121_nfc_prv *prv = chip->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct mpc5121_nfc_prv *prv = nand_get_controller_data(chip);
 	uint c = prv->column;
 	uint l;
 
@@ -489,7 +488,7 @@
 static int mpc5121_nfc_read_hw_config(struct mtd_info *mtd)
 {
 	immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 	uint rcw_pagesize = 0;
 	uint rcw_sparesize = 0;
 	uint rcw_width;
@@ -549,7 +548,6 @@
 	int resettime = 0;
 	int retval = 0;
 	int rev;
-	static int chip_nr = 0;
 
 	/*
 	 * Check SoC revision. This driver supports only NFC
@@ -568,9 +566,8 @@
 		return -ENOMEM;
 	}
 
-	mtd = &nand_info[chip_nr++];
-	mtd->priv = chip;
-	chip->priv = prv;
+	mtd = &chip->mtd;
+	nand_set_controller_data(chip, prv);
 
 	/* Read NFC configuration from Reset Config Word */
 	retval = mpc5121_nfc_read_hw_config(mtd);
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index f12b07e..7221d0b 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -19,7 +19,6 @@
 #define DRIVER_NAME "mxc_nand"
 
 struct mxc_nand_host {
-	struct mtd_info			mtd;
 	struct nand_chip		*nand;
 
 	struct mxc_nand_regs __iomem	*regs;
@@ -351,8 +350,8 @@
 
 static void _mxc_nand_enable_hwecc(struct mtd_info *mtd, int on)
 {
-	struct nand_chip *nand_chip = mtd->priv;
-	struct mxc_nand_host *host = nand_chip->priv;
+	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
 #if defined(MXC_NFC_V1) || defined(MXC_NFC_V2_1)
 	uint16_t tmp = readnfc(&host->regs->config1);
 
@@ -386,7 +385,7 @@
 				      struct nand_chip *chip,
 				      int page)
 {
-	struct mxc_nand_host *host = chip->priv;
+	struct mxc_nand_host *host = nand_get_controller_data(chip);
 	uint8_t *buf = chip->oob_poi;
 	int length = mtd->oobsize;
 	int eccpitch = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad;
@@ -441,7 +440,7 @@
 					   int oob_required,
 					   int page)
 {
-	struct mxc_nand_host *host = chip->priv;
+	struct mxc_nand_host *host = nand_get_controller_data(chip);
 	int eccsize = chip->ecc.size;
 	int eccbytes = chip->ecc.bytes;
 	int eccpitch = eccbytes + chip->ecc.prepad + chip->ecc.postpad;
@@ -486,7 +485,7 @@
 				       int oob_required,
 				       int page)
 {
-	struct mxc_nand_host *host = chip->priv;
+	struct mxc_nand_host *host = nand_get_controller_data(chip);
 	int n, eccsize = chip->ecc.size;
 	int eccbytes = chip->ecc.bytes;
 	int eccpitch = eccbytes + chip->ecc.prepad + chip->ecc.postpad;
@@ -550,7 +549,7 @@
 static int mxc_nand_write_oob_syndrome(struct mtd_info *mtd,
 				       struct nand_chip *chip, int page)
 {
-	struct mxc_nand_host *host = chip->priv;
+	struct mxc_nand_host *host = nand_get_controller_data(chip);
 	int eccpitch = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad;
 	int length = mtd->oobsize;
 	int i, len, status, steps = chip->ecc.steps;
@@ -576,9 +575,9 @@
 static int mxc_nand_write_page_raw_syndrome(struct mtd_info *mtd,
 					     struct nand_chip *chip,
 					     const uint8_t *buf,
-					     int oob_required)
+					     int oob_required, int page)
 {
-	struct mxc_nand_host *host = chip->priv;
+	struct mxc_nand_host *host = nand_get_controller_data(chip);
 	int eccsize = chip->ecc.size;
 	int eccbytes = chip->ecc.bytes;
 	int eccpitch = eccbytes + chip->ecc.prepad + chip->ecc.postpad;
@@ -616,9 +615,9 @@
 static int mxc_nand_write_page_syndrome(struct mtd_info *mtd,
 					 struct nand_chip *chip,
 					 const uint8_t *buf,
-					 int oob_required)
+					 int oob_required, int page)
 {
-	struct mxc_nand_host *host = chip->priv;
+	struct mxc_nand_host *host = nand_get_controller_data(chip);
 	int i, n, eccsize = chip->ecc.size;
 	int eccbytes = chip->ecc.bytes;
 	int eccpitch = eccbytes + chip->ecc.prepad + chip->ecc.postpad;
@@ -661,8 +660,8 @@
 static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat,
 				 u_char *read_ecc, u_char *calc_ecc)
 {
-	struct nand_chip *nand_chip = mtd->priv;
-	struct mxc_nand_host *host = nand_chip->priv;
+	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
 	uint32_t ecc_status = readl(&host->regs->ecc_status_result);
 	int subpages = mtd->writesize / nand_chip->subpagesize;
 	int pg2blk_shift = nand_chip->phys_erase_shift -
@@ -681,7 +680,7 @@
 				       mtd->writesize / nand_chip->subpagesize
 					    - subpages);
 			}
-			return -1;
+			return -EBADMSG;
 		}
 		ecc_status >>= 4;
 		subpages--;
@@ -700,8 +699,8 @@
 static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat,
 				 u_char *read_ecc, u_char *calc_ecc)
 {
-	struct nand_chip *nand_chip = mtd->priv;
-	struct mxc_nand_host *host = nand_chip->priv;
+	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
 
 	/*
 	 * 1-Bit errors are automatically corrected in HW.  No need for
@@ -713,7 +712,7 @@
 	if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) {
 		MTDDEBUG(MTD_DEBUG_LEVEL0,
 		      "MXC_NAND: HWECC uncorrectable 2-bit ECC error\n");
-		return -1;
+		return -EBADMSG;
 	}
 
 	return 0;
@@ -729,8 +728,8 @@
 
 static u_char mxc_nand_read_byte(struct mtd_info *mtd)
 {
-	struct nand_chip *nand_chip = mtd->priv;
-	struct mxc_nand_host *host = nand_chip->priv;
+	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
 	uint8_t ret = 0;
 	uint16_t col;
 	uint16_t __iomem *main_buf =
@@ -769,8 +768,8 @@
 
 static uint16_t mxc_nand_read_word(struct mtd_info *mtd)
 {
-	struct nand_chip *nand_chip = mtd->priv;
-	struct mxc_nand_host *host = nand_chip->priv;
+	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
 	uint16_t col, ret;
 	uint16_t __iomem *p;
 
@@ -821,8 +820,8 @@
 static void mxc_nand_write_buf(struct mtd_info *mtd,
 				const u_char *buf, int len)
 {
-	struct nand_chip *nand_chip = mtd->priv;
-	struct mxc_nand_host *host = nand_chip->priv;
+	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
 	int n, col, i = 0;
 
 	MTDDEBUG(MTD_DEBUG_LEVEL3,
@@ -895,8 +894,8 @@
  */
 static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
 {
-	struct nand_chip *nand_chip = mtd->priv;
-	struct mxc_nand_host *host = nand_chip->priv;
+	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
 	int n, col, i = 0;
 
 	MTDDEBUG(MTD_DEBUG_LEVEL3,
@@ -955,8 +954,8 @@
  */
 static void mxc_nand_select_chip(struct mtd_info *mtd, int chip)
 {
-	struct nand_chip *nand_chip = mtd->priv;
-	struct mxc_nand_host *host = nand_chip->priv;
+	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
 
 	switch (chip) {
 	case -1:
@@ -982,8 +981,8 @@
 void mxc_nand_command(struct mtd_info *mtd, unsigned command,
 				int column, int page_addr)
 {
-	struct nand_chip *nand_chip = mtd->priv;
-	struct mxc_nand_host *host = nand_chip->priv;
+	struct nand_chip *nand_chip = mtd_to_nand(mtd);
+	struct mxc_nand_host *host = nand_get_controller_data(nand_chip);
 
 	MTDDEBUG(MTD_DEBUG_LEVEL3,
 	      "mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n",
@@ -1164,14 +1163,13 @@
 #endif
 
 	/* structures must be linked */
-	mtd = &host->mtd;
-	mtd->priv = this;
+	mtd = &this->mtd;
 	host->nand = this;
 
 	/* 5 us command delay time */
 	this->chip_delay = 5;
 
-	this->priv = host;
+	nand_set_controller_data(this, host);
 	this->dev_ready = mxc_nand_dev_ready;
 	this->cmdfunc = mxc_nand_command;
 	this->select_chip = mxc_nand_select_chip;
diff --git a/drivers/mtd/nand/mxc_nand_spl.c b/drivers/mtd/nand/mxc_nand_spl.c
index 6ac2c96..841fb5b 100644
--- a/drivers/mtd/nand/mxc_nand_spl.c
+++ b/drivers/mtd/nand/mxc_nand_spl.c
@@ -232,7 +232,7 @@
 	nfc_nand_read_page(page_address);
 
 	if (nfc_nand_check_ecc())
-		return -1;
+		return -EBADMSG;
 
 	src = (u32 *)&nfc->main_area[0][0];
 	dst = (u32 *)buf;
diff --git a/drivers/mtd/nand/mxs_nand.c b/drivers/mtd/nand/mxs_nand.c
index b5bbd88..7be1f86 100644
--- a/drivers/mtd/nand/mxs_nand.c
+++ b/drivers/mtd/nand/mxs_nand.c
@@ -264,8 +264,8 @@
  */
 static void mxs_nand_cmd_ctrl(struct mtd_info *mtd, int data, unsigned int ctrl)
 {
-	struct nand_chip *nand = mtd->priv;
-	struct mxs_nand_info *nand_info = nand->priv;
+	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
 	struct mxs_dma_desc *d;
 	uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip;
 	int ret;
@@ -343,8 +343,8 @@
  */
 static int mxs_nand_device_ready(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd->priv;
-	struct mxs_nand_info *nand_info = chip->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
 	struct mxs_gpmi_regs *gpmi_regs =
 		(struct mxs_gpmi_regs *)MXS_GPMI_BASE;
 	uint32_t tmp;
@@ -360,8 +360,8 @@
  */
 static void mxs_nand_select_chip(struct mtd_info *mtd, int chip)
 {
-	struct nand_chip *nand = mtd->priv;
-	struct mxs_nand_info *nand_info = nand->priv;
+	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
 
 	nand_info->cur_chip = chip;
 }
@@ -410,8 +410,8 @@
  */
 static void mxs_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int length)
 {
-	struct nand_chip *nand = mtd->priv;
-	struct mxs_nand_info *nand_info = nand->priv;
+	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
 	struct mxs_dma_desc *d;
 	uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip;
 	int ret;
@@ -494,8 +494,8 @@
 static void mxs_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf,
 				int length)
 {
-	struct nand_chip *nand = mtd->priv;
-	struct mxs_nand_info *nand_info = nand->priv;
+	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
 	struct mxs_dma_desc *d;
 	uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip;
 	int ret;
@@ -559,7 +559,7 @@
 					uint8_t *buf, int oob_required,
 					int page)
 {
-	struct mxs_nand_info *nand_info = nand->priv;
+	struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
 	struct mxs_dma_desc *d;
 	uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip;
 	uint32_t corrected = 0, failed = 0;
@@ -707,9 +707,9 @@
  */
 static int mxs_nand_ecc_write_page(struct mtd_info *mtd,
 				struct nand_chip *nand, const uint8_t *buf,
-				int oob_required)
+				int oob_required, int page)
 {
-	struct mxs_nand_info *nand_info = nand->priv;
+	struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
 	struct mxs_dma_desc *d;
 	uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip;
 	int ret;
@@ -775,8 +775,8 @@
 static int mxs_nand_hook_read_oob(struct mtd_info *mtd, loff_t from,
 					struct mtd_oob_ops *ops)
 {
-	struct nand_chip *chip = mtd->priv;
-	struct mxs_nand_info *nand_info = chip->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
 	int ret;
 
 	if (ops->mode == MTD_OPS_RAW)
@@ -800,8 +800,8 @@
 static int mxs_nand_hook_write_oob(struct mtd_info *mtd, loff_t to,
 					struct mtd_oob_ops *ops)
 {
-	struct nand_chip *chip = mtd->priv;
-	struct mxs_nand_info *nand_info = chip->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
 	int ret;
 
 	if (ops->mode == MTD_OPS_RAW)
@@ -824,8 +824,8 @@
  */
 static int mxs_nand_hook_block_markbad(struct mtd_info *mtd, loff_t ofs)
 {
-	struct nand_chip *chip = mtd->priv;
-	struct mxs_nand_info *nand_info = chip->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
 	int ret;
 
 	nand_info->marking_block_bad = 1;
@@ -884,7 +884,7 @@
 static int mxs_nand_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *nand,
 				int page)
 {
-	struct mxs_nand_info *nand_info = nand->priv;
+	struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
 
 	/*
 	 * First, fill in the OOB buffer. If we're doing a raw read, we need to
@@ -919,7 +919,7 @@
 static int mxs_nand_ecc_write_oob(struct mtd_info *mtd, struct nand_chip *nand,
 					int page)
 {
-	struct mxs_nand_info *nand_info = nand->priv;
+	struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
 	uint8_t block_mark = 0;
 
 	/*
@@ -961,7 +961,7 @@
  * Thus, this function is only called when we want *all* blocks to look good,
  * so it *always* return success.
  */
-static int mxs_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
+static int mxs_nand_block_bad(struct mtd_info *mtd, loff_t ofs)
 {
 	return 0;
 }
@@ -982,8 +982,8 @@
  */
 static int mxs_nand_scan_bbt(struct mtd_info *mtd)
 {
-	struct nand_chip *nand = mtd->priv;
-	struct mxs_nand_info *nand_info = nand->priv;
+	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
 	struct mxs_bch_regs *bch_regs = (struct mxs_bch_regs *)MXS_BCH_BASE;
 	uint32_t tmp;
 
@@ -1175,7 +1175,7 @@
 
 	memset(&fake_ecc_layout, 0, sizeof(fake_ecc_layout));
 
-	nand->priv = nand_info;
+	nand_set_controller_data(nand, nand_info);
 	nand->options |= NAND_NO_SUBPAGE_WRITE;
 
 	nand->cmd_ctrl		= mxs_nand_cmd_ctrl;
diff --git a/drivers/mtd/nand/mxs_nand_spl.c b/drivers/mtd/nand/mxs_nand_spl.c
index 0e7c364..a8a3084 100644
--- a/drivers/mtd/nand/mxs_nand_spl.c
+++ b/drivers/mtd/nand/mxs_nand_spl.c
@@ -8,13 +8,13 @@
 #include <nand.h>
 #include <malloc.h>
 
-static nand_info_t mtd;
+static struct mtd_info *mtd;
 static struct nand_chip nand_chip;
 
 static void mxs_nand_command(struct mtd_info *mtd, unsigned int command,
 			     int column, int page_addr)
 {
-	register struct nand_chip *chip = mtd->priv;
+	register struct nand_chip *chip = mtd_to_nand(mtd);
 	u32 timeo, time_start;
 
 	/* write out the command to the device */
@@ -51,7 +51,7 @@
 
 static int mxs_flash_ident(struct mtd_info *mtd)
 {
-	register struct nand_chip *chip = mtd->priv;
+	register struct nand_chip *chip = mtd_to_nand(mtd);
 	int i;
 	u8 mfg_id, dev_id;
 	u8 id_data[8];
@@ -111,7 +111,7 @@
 
 static int mxs_read_page_ecc(struct mtd_info *mtd, void *buf, unsigned int page)
 {
-	register struct nand_chip *chip = mtd->priv;
+	register struct nand_chip *chip = mtd_to_nand(mtd);
 	int ret;
 
 	chip->cmdfunc(mtd, NAND_CMD_READ0, 0x0, page);
@@ -125,7 +125,7 @@
 
 static int is_badblock(struct mtd_info *mtd, loff_t offs, int allowbbt)
 {
-	register struct nand_chip *chip = mtd->priv;
+	register struct nand_chip *chip = mtd_to_nand(mtd);
 	unsigned int block = offs >> chip->phys_erase_shift;
 	unsigned int page = offs >> chip->page_shift;
 
@@ -147,14 +147,14 @@
 
 	/* init mxs nand driver */
 	board_nand_init(&nand_chip);
-	mtd.priv = &nand_chip;
+	mtd = &nand_chip.mtd;
 	/* set mtd functions */
 	nand_chip.cmdfunc = mxs_nand_command;
 	nand_chip.numchips = 1;
 
 	/* identify flash device */
 	puts("NAND : ");
-	if (mxs_flash_ident(&mtd)) {
+	if (mxs_flash_ident(mtd)) {
 		printf("Failed to identify\n");
 		return -1;
 	}
@@ -162,12 +162,12 @@
 	/* allocate and initialize buffers */
 	nand_chip.buffers = memalign(ARCH_DMA_MINALIGN,
 				     sizeof(*nand_chip.buffers));
-	nand_chip.oob_poi = nand_chip.buffers->databuf + mtd.writesize;
+	nand_chip.oob_poi = nand_chip.buffers->databuf + mtd->writesize;
 	/* setup flash layout (does not scan as we override that) */
-	mtd.size = nand_chip.chipsize;
-	nand_chip.scan_bbt(&mtd);
+	mtd->size = nand_chip.chipsize;
+	nand_chip.scan_bbt(mtd);
 
-	printf("%llu MiB\n", (mtd.size / (1024 * 1024)));
+	printf("%llu MiB\n", (mtd->size / (1024 * 1024)));
 	return 0;
 }
 
@@ -180,20 +180,20 @@
 
 	if (mxs_nand_init())
 		return -ENODEV;
-	chip = mtd.priv;
+	chip = mtd_to_nand(mtd);
 	page = offs >> chip->page_shift;
-	nand_page_per_block = mtd.erasesize / mtd.writesize;
+	nand_page_per_block = mtd->erasesize / mtd->writesize;
 
 	debug("%s offset:0x%08x len:%d page:%d\n", __func__, offs, size, page);
 
-	size = roundup(size, mtd.writesize);
+	size = roundup(size, mtd->writesize);
 	while (sz < size) {
-		if (mxs_read_page_ecc(&mtd, buf, page) < 0)
+		if (mxs_read_page_ecc(mtd, buf, page) < 0)
 			return -1;
-		sz += mtd.writesize;
-		offs += mtd.writesize;
+		sz += mtd->writesize;
+		offs += mtd->writesize;
 		page++;
-		buf += mtd.writesize;
+		buf += mtd->writesize;
 
 		/*
 		 * Check if we have crossed a block boundary, and if so
@@ -204,10 +204,10 @@
 			 * Yes, new block. See if this block is good. If not,
 			 * loop until we find a good block.
 			 */
-			while (is_badblock(&mtd, offs, 1)) {
+			while (is_badblock(mtd, offs, 1)) {
 				page = page + nand_page_per_block;
 				/* Check i we've reached the end of flash. */
-				if (page >= mtd.size >> chip->page_shift)
+				if (page >= mtd->size >> chip->page_shift)
 					return -ENOMEM;
 			}
 		}
diff --git a/drivers/mtd/nand/nand.c b/drivers/mtd/nand/nand.c
index 8f0a921..f449316 100644
--- a/drivers/mtd/nand/nand.c
+++ b/drivers/mtd/nand/nand.c
@@ -19,7 +19,7 @@
 int nand_curr_device = -1;
 
 
-nand_info_t nand_info[CONFIG_SYS_MAX_NAND_DEVICE];
+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];
@@ -30,15 +30,25 @@
 
 static unsigned long total_nand_size; /* in kiB */
 
-/* Register an initialized NAND mtd device with the U-Boot NAND command. */
-int nand_register(int devnum)
+int nand_mtd_to_devnum(struct mtd_info *mtd)
 {
-	struct mtd_info *mtd;
+	int i;
 
+	for (i = 0; i < ARRAY_SIZE(nand_info); i++) {
+		if (mtd && nand_info[i] == mtd)
+			return i;
+	}
+
+	return -ENODEV;
+}
+
+/* Register an initialized NAND mtd device with the U-Boot NAND command. */
+int nand_register(int devnum, struct mtd_info *mtd)
+{
 	if (devnum >= CONFIG_SYS_MAX_NAND_DEVICE)
 		return -EINVAL;
 
-	mtd = &nand_info[devnum];
+	nand_info[devnum] = mtd;
 
 	sprintf(dev_name[devnum], "nand%d", devnum);
 	mtd->name = dev_name[devnum];
@@ -62,15 +72,14 @@
 #ifndef CONFIG_SYS_NAND_SELF_INIT
 static void nand_init_chip(int i)
 {
-	struct mtd_info *mtd = &nand_info[i];
 	struct nand_chip *nand = &nand_chip[i];
+	struct mtd_info *mtd = nand_to_mtd(nand);
 	ulong base_addr = base_address[i];
 	int maxchips = CONFIG_SYS_NAND_MAX_CHIPS;
 
 	if (maxchips < 1)
 		maxchips = 1;
 
-	mtd->priv = nand;
 	nand->IO_ADDR_R = nand->IO_ADDR_W = (void  __iomem *)base_addr;
 
 	if (board_nand_init(nand))
@@ -79,7 +88,7 @@
 	if (nand_scan(mtd, maxchips))
 		return;
 
-	nand_register(i);
+	nand_register(i, mtd);
 }
 #endif
 
@@ -100,6 +109,7 @@
 	/*
 	 * Select the chip in the board/cpu specific driver
 	 */
-	board_nand_select_device(nand_info[nand_curr_device].priv, nand_curr_device);
+	board_nand_select_device(mtd_to_nand(nand_info[nand_curr_device]),
+				 nand_curr_device);
 #endif
 }
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 9e8fc1f..74c563c 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -1,6 +1,4 @@
 /*
- *  drivers/mtd/nand.c
- *
  *  Overview:
  *   This is the generic MTD driver for NAND flash devices. It should be
  *   capable of working with almost all NAND chips currently available.
@@ -45,8 +43,6 @@
 #include <asm/io.h>
 #include <asm/errno.h>
 
-static bool is_module_text_address(unsigned long addr) {return 0;}
-
 /* Define default oob placement schemes for large and small page devices */
 static struct nand_ecclayout nand_oob_8 = {
 	.eccbytes = 3,
@@ -105,7 +101,7 @@
 static int check_offs_len(struct mtd_info *mtd,
 					loff_t ofs, uint64_t len)
 {
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 	int ret = 0;
 
 	/* Start address must align on block boundary */
@@ -131,7 +127,7 @@
  */
 static void nand_release_device(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 
 	/* De-select the NAND device */
 	chip->select_chip(mtd, -1);
@@ -145,7 +141,7 @@
  */
 uint8_t nand_read_byte(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 	return readb(chip->IO_ADDR_R);
 }
 
@@ -158,7 +154,7 @@
  */
 static uint8_t nand_read_byte16(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 	return (uint8_t) cpu_to_le16(readw(chip->IO_ADDR_R));
 }
 
@@ -170,7 +166,7 @@
  */
 static u16 nand_read_word(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 	return readw(chip->IO_ADDR_R);
 }
 
@@ -183,7 +179,7 @@
  */
 static void nand_select_chip(struct mtd_info *mtd, int chipnr)
 {
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 
 	switch (chipnr) {
 	case -1:
@@ -206,7 +202,7 @@
  */
 static void nand_write_byte(struct mtd_info *mtd, uint8_t byte)
 {
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 
 	chip->write_buf(mtd, &byte, 1);
 }
@@ -220,7 +216,7 @@
  */
 static void nand_write_byte16(struct mtd_info *mtd, uint8_t byte)
 {
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 	uint16_t word = byte;
 
 	/*
@@ -287,7 +283,7 @@
  */
 void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
 {
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 
 	iowrite8_rep(chip->IO_ADDR_W, buf, len);
 }
@@ -302,7 +298,7 @@
  */
 void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 {
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 
 	ioread8_rep(chip->IO_ADDR_R, buf, len);
 }
@@ -317,7 +313,7 @@
  */
 void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
 {
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 	u16 *p = (u16 *) buf;
 
 	iowrite16_rep(chip->IO_ADDR_W, p, len >> 1);
@@ -333,7 +329,7 @@
  */
 void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len)
 {
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 	u16 *p = (u16 *) buf;
 
 	ioread16_rep(chip->IO_ADDR_R, p, len >> 1);
@@ -343,14 +339,13 @@
  * nand_block_bad - [DEFAULT] Read bad block marker from the chip
  * @mtd: MTD device structure
  * @ofs: offset from device start
- * @getchip: 0, if the chip is already selected
  *
  * Check, if the block is bad.
  */
-static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
+static int nand_block_bad(struct mtd_info *mtd, loff_t ofs)
 {
-	int page, chipnr, res = 0, i = 0;
-	struct nand_chip *chip = mtd->priv;
+	int page, res = 0, i = 0;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 	u16 bad;
 
 	if (chip->bbt_options & NAND_BBT_SCANLASTPAGE)
@@ -358,15 +353,6 @@
 
 	page = (int)(ofs >> chip->page_shift) & chip->pagemask;
 
-	if (getchip) {
-		chipnr = (int)(ofs >> chip->chip_shift);
-
-		nand_get_device(mtd, FL_READING);
-
-		/* Select the NAND device */
-		chip->select_chip(mtd, chipnr);
-	}
-
 	do {
 		if (chip->options & NAND_BUSWIDTH_16) {
 			chip->cmdfunc(mtd, NAND_CMD_READOOB,
@@ -391,11 +377,6 @@
 		i++;
 	} while (!res && i < 2 && (chip->bbt_options & NAND_BBT_SCAN2NDPAGE));
 
-	if (getchip) {
-		chip->select_chip(mtd, -1);
-		nand_release_device(mtd);
-	}
-
 	return res;
 }
 
@@ -410,7 +391,7 @@
  */
 static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
 {
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 	struct mtd_oob_ops ops;
 	uint8_t buf[2] = { 0, 0 };
 	int ret = 0, res, i = 0;
@@ -460,7 +441,7 @@
 */
 static int nand_block_markbad_lowlevel(struct mtd_info *mtd, loff_t ofs)
 {
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 	int res, ret = 0;
 
 	if (!(chip->bbt_options & NAND_BBT_NO_OOB_BBM)) {
@@ -501,7 +482,7 @@
  */
 static int nand_check_wp(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 
 	/* Broken xD cards report WP despite being writable */
 	if (chip->options & NAND_BROKEN_XD)
@@ -521,7 +502,7 @@
  */
 static int nand_block_isreserved(struct mtd_info *mtd, loff_t ofs)
 {
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 
 	if (!chip->bbt)
 		return 0;
@@ -533,16 +514,14 @@
  * nand_block_checkbad - [GENERIC] Check if a block is marked bad
  * @mtd: MTD device structure
  * @ofs: offset from device start
- * @getchip: 0, if the chip is already selected
  * @allowbbt: 1, if its allowed to access the bbt area
  *
  * Check, if the block is bad. Either by reading the bad block table or
  * calling of the scan function.
  */
-static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip,
-			       int allowbbt)
+static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int allowbbt)
 {
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 
 	if (!(chip->options & NAND_SKIP_BBTSCAN) &&
 	    !(chip->options & NAND_BBT_SCANNED)) {
@@ -551,17 +530,22 @@
 	}
 
 	if (!chip->bbt)
-		return chip->block_bad(mtd, ofs, getchip);
+		return chip->block_bad(mtd, ofs);
 
 	/* Return info from the table */
 	return nand_isbad_bbt(mtd, ofs, allowbbt);
 }
 
-/* Wait for the ready pin, after a command. The timeout is caught later. */
+/**
+ * nand_wait_ready - [GENERIC] Wait for the ready pin after commands.
+ * @mtd: MTD device structure
+ *
+ * Wait for the ready pin after a command, and warn if a timeout occurs.
+ */
 void nand_wait_ready(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd->priv;
-	u32 timeo = (CONFIG_SYS_HZ * 20) / 1000;
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	u32 timeo = (CONFIG_SYS_HZ * 400) / 1000;
 	u32 time_start;
 
 	time_start = get_timer(0);
@@ -571,6 +555,9 @@
 			if (chip->dev_ready(mtd))
 				break;
 	}
+
+	if (!chip->dev_ready(mtd))
+		pr_warn("timeout while waiting for chip to become ready\n");
 }
 EXPORT_SYMBOL_GPL(nand_wait_ready);
 
@@ -583,7 +570,7 @@
  */
 static void nand_wait_status_ready(struct mtd_info *mtd, unsigned long timeo)
 {
-	register struct nand_chip *chip = mtd->priv;
+	register struct nand_chip *chip = mtd_to_nand(mtd);
 	u32 time_start;
 
 	timeo = (CONFIG_SYS_HZ * timeo) / 1000;
@@ -608,7 +595,7 @@
 static void nand_command(struct mtd_info *mtd, unsigned int command,
 			 int column, int page_addr)
 {
-	register struct nand_chip *chip = mtd->priv;
+	register struct nand_chip *chip = mtd_to_nand(mtd);
 	int ctrl = NAND_CTRL_CLE | NAND_CTRL_CHANGE;
 
 	/* Write out the command to the device */
@@ -711,7 +698,7 @@
 static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
 			    int column, int page_addr)
 {
-	register struct nand_chip *chip = mtd->priv;
+	register struct nand_chip *chip = mtd_to_nand(mtd);
 
 	/* Emulate NAND_CMD_READOOB */
 	if (command == NAND_CMD_READOOB) {
@@ -835,7 +822,7 @@
 static int
 nand_get_device(struct mtd_info *mtd, int new_state)
 {
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 	chip->state = new_state;
 	return 0;
 }
@@ -871,15 +858,13 @@
  * @mtd: MTD device structure
  * @chip: NAND chip structure
  *
- * Wait for command done. This applies to erase and program only. Erase can
- * take up to 400ms and program up to 20ms according to general NAND and
- * SmartMedia specs.
+ * Wait for command done. This applies to erase and program only.
  */
 static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
 {
 
-	int status, state = chip->state;
-	unsigned long timeo = (state == FL_ERASING ? 400 : 20);
+	int status;
+	unsigned long timeo = 400;
 
 	led_trigger_event(nand_led_trigger, LED_FULL);
 
@@ -911,6 +896,135 @@
 	WARN_ON(!(status & NAND_STATUS_READY));
 	return status;
 }
+
+#define BITS_PER_BYTE 8
+
+/**
+ * nand_check_erased_buf - check if a buffer contains (almost) only 0xff data
+ * @buf: buffer to test
+ * @len: buffer length
+ * @bitflips_threshold: maximum number of bitflips
+ *
+ * Check if a buffer contains only 0xff, which means the underlying region
+ * has been erased and is ready to be programmed.
+ * The bitflips_threshold specify the maximum number of bitflips before
+ * considering the region is not erased.
+ * Note: The logic of this function has been extracted from the memweight
+ * implementation, except that nand_check_erased_buf function exit before
+ * testing the whole buffer if the number of bitflips exceed the
+ * bitflips_threshold value.
+ *
+ * Returns a positive number of bitflips less than or equal to
+ * bitflips_threshold, or -ERROR_CODE for bitflips in excess of the
+ * threshold.
+ */
+static int nand_check_erased_buf(void *buf, int len, int bitflips_threshold)
+{
+	const unsigned char *bitmap = buf;
+	int bitflips = 0;
+	int weight;
+
+	for (; len && ((uintptr_t)bitmap) % sizeof(long);
+	     len--, bitmap++) {
+		weight = hweight8(*bitmap);
+		bitflips += BITS_PER_BYTE - weight;
+		if (unlikely(bitflips > bitflips_threshold))
+			return -EBADMSG;
+	}
+
+	for (; len >= 4; len -= 4, bitmap += 4) {
+		weight = hweight32(*((u32 *)bitmap));
+		bitflips += 32 - weight;
+		if (unlikely(bitflips > bitflips_threshold))
+			return -EBADMSG;
+	}
+
+	for (; len > 0; len--, bitmap++) {
+		weight = hweight8(*bitmap);
+		bitflips += BITS_PER_BYTE - weight;
+		if (unlikely(bitflips > bitflips_threshold))
+			return -EBADMSG;
+	}
+
+	return bitflips;
+}
+
+/**
+ * nand_check_erased_ecc_chunk - check if an ECC chunk contains (almost) only
+ *				 0xff data
+ * @data: data buffer to test
+ * @datalen: data length
+ * @ecc: ECC buffer
+ * @ecclen: ECC length
+ * @extraoob: extra OOB buffer
+ * @extraooblen: extra OOB length
+ * @bitflips_threshold: maximum number of bitflips
+ *
+ * Check if a data buffer and its associated ECC and OOB data contains only
+ * 0xff pattern, which means the underlying region has been erased and is
+ * ready to be programmed.
+ * The bitflips_threshold specify the maximum number of bitflips before
+ * considering the region as not erased.
+ *
+ * Note:
+ * 1/ ECC algorithms are working on pre-defined block sizes which are usually
+ *    different from the NAND page size. When fixing bitflips, ECC engines will
+ *    report the number of errors per chunk, and the NAND core infrastructure
+ *    expect you to return the maximum number of bitflips for the whole page.
+ *    This is why you should always use this function on a single chunk and
+ *    not on the whole page. After checking each chunk you should update your
+ *    max_bitflips value accordingly.
+ * 2/ When checking for bitflips in erased pages you should not only check
+ *    the payload data but also their associated ECC data, because a user might
+ *    have programmed almost all bits to 1 but a few. In this case, we
+ *    shouldn't consider the chunk as erased, and checking ECC bytes prevent
+ *    this case.
+ * 3/ The extraoob argument is optional, and should be used if some of your OOB
+ *    data are protected by the ECC engine.
+ *    It could also be used if you support subpages and want to attach some
+ *    extra OOB data to an ECC chunk.
+ *
+ * Returns a positive number of bitflips less than or equal to
+ * bitflips_threshold, or -ERROR_CODE for bitflips in excess of the
+ * threshold. In case of success, the passed buffers are filled with 0xff.
+ */
+int nand_check_erased_ecc_chunk(void *data, int datalen,
+				void *ecc, int ecclen,
+				void *extraoob, int extraooblen,
+				int bitflips_threshold)
+{
+	int data_bitflips = 0, ecc_bitflips = 0, extraoob_bitflips = 0;
+
+	data_bitflips = nand_check_erased_buf(data, datalen,
+					      bitflips_threshold);
+	if (data_bitflips < 0)
+		return data_bitflips;
+
+	bitflips_threshold -= data_bitflips;
+
+	ecc_bitflips = nand_check_erased_buf(ecc, ecclen, bitflips_threshold);
+	if (ecc_bitflips < 0)
+		return ecc_bitflips;
+
+	bitflips_threshold -= ecc_bitflips;
+
+	extraoob_bitflips = nand_check_erased_buf(extraoob, extraooblen,
+						  bitflips_threshold);
+	if (extraoob_bitflips < 0)
+		return extraoob_bitflips;
+
+	if (data_bitflips)
+		memset(data, 0xff, datalen);
+
+	if (ecc_bitflips)
+		memset(ecc, 0xff, ecclen);
+
+	if (extraoob_bitflips)
+		memset(extraoob, 0xff, extraooblen);
+
+	return data_bitflips + ecc_bitflips + extraoob_bitflips;
+}
+EXPORT_SYMBOL(nand_check_erased_ecc_chunk);
 
 /**
  * nand_read_page_raw - [INTERN] read raw page data without ecc
@@ -1103,6 +1217,16 @@
 
 		stat = chip->ecc.correct(mtd, p,
 			&chip->buffers->ecccode[i], &chip->buffers->ecccalc[i]);
+		if (stat == -EBADMSG &&
+		    (chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) {
+			/* check for empty pages with bitflips */
+			stat = nand_check_erased_ecc_chunk(p, chip->ecc.size,
+						&chip->buffers->ecccode[i],
+						chip->ecc.bytes,
+						NULL, 0,
+						chip->ecc.strength);
+		}
+
 		if (stat < 0) {
 			mtd->ecc_stats.failed++;
 		} else {
@@ -1152,6 +1276,15 @@
 		int stat;
 
 		stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
+		if (stat == -EBADMSG &&
+		    (chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) {
+			/* check for empty pages with bitflips */
+			stat = nand_check_erased_ecc_chunk(p, eccsize,
+						&ecc_code[i], eccbytes,
+						NULL, 0,
+						chip->ecc.strength);
+		}
+
 		if (stat < 0) {
 			mtd->ecc_stats.failed++;
 		} else {
@@ -1204,6 +1337,15 @@
 		chip->ecc.calculate(mtd, p, &ecc_calc[i]);
 
 		stat = chip->ecc.correct(mtd, p, &ecc_code[i], NULL);
+		if (stat == -EBADMSG &&
+		    (chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) {
+			/* check for empty pages with bitflips */
+			stat = nand_check_erased_ecc_chunk(p, eccsize,
+						&ecc_code[i], eccbytes,
+						NULL, 0,
+						chip->ecc.strength);
+		}
+
 		if (stat < 0) {
 			mtd->ecc_stats.failed++;
 		} else {
@@ -1231,6 +1373,7 @@
 	int i, eccsize = chip->ecc.size;
 	int eccbytes = chip->ecc.bytes;
 	int eccsteps = chip->ecc.steps;
+	int eccpadbytes = eccbytes + chip->ecc.prepad + chip->ecc.postpad;
 	uint8_t *p = buf;
 	uint8_t *oob = chip->oob_poi;
 	unsigned int max_bitflips = 0;
@@ -1250,19 +1393,29 @@
 		chip->read_buf(mtd, oob, eccbytes);
 		stat = chip->ecc.correct(mtd, p, oob, NULL);
 
-		if (stat < 0) {
-			mtd->ecc_stats.failed++;
-		} else {
-			mtd->ecc_stats.corrected += stat;
-			max_bitflips = max_t(unsigned int, max_bitflips, stat);
-		}
-
 		oob += eccbytes;
 
 		if (chip->ecc.postpad) {
 			chip->read_buf(mtd, oob, chip->ecc.postpad);
 			oob += chip->ecc.postpad;
 		}
+
+		if (stat == -EBADMSG &&
+		    (chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) {
+			/* check for empty pages with bitflips */
+			stat = nand_check_erased_ecc_chunk(p, chip->ecc.size,
+							   oob - eccpadbytes,
+							   eccpadbytes,
+							   NULL, 0,
+							   chip->ecc.strength);
+		}
+
+		if (stat < 0) {
+			mtd->ecc_stats.failed++;
+		} else {
+			mtd->ecc_stats.corrected += stat;
+			max_bitflips = max_t(unsigned int, max_bitflips, stat);
+		}
 	}
 
 	/* Calculate remaining oob bytes */
@@ -1332,7 +1485,7 @@
  */
 static int nand_setup_read_retry(struct mtd_info *mtd, int retry_mode)
 {
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 
 	pr_debug("setting READ RETRY mode %d\n", retry_mode);
 
@@ -1357,12 +1510,11 @@
 			    struct mtd_oob_ops *ops)
 {
 	int chipnr, page, realpage, col, bytes, aligned, oob_required;
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 	int ret = 0;
 	uint32_t readlen = ops->len;
 	uint32_t oobreadlen = ops->ooblen;
-	uint32_t max_oobsize = ops->mode == MTD_OPS_AUTO_OOB ?
-		mtd->oobavail : mtd->oobsize;
+	uint32_t max_oobsize = mtd_oobavail(mtd, ops);
 
 	uint8_t *bufpoi, *oob, *buf;
 	int use_bufpoi;
@@ -1700,7 +1852,7 @@
 			    struct mtd_oob_ops *ops)
 {
 	int page, realpage, chipnr;
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 	struct mtd_ecc_stats stats;
 	int readlen = ops->ooblen;
 	int len;
@@ -1712,10 +1864,7 @@
 
 	stats = mtd->ecc_stats;
 
-	if (ops->mode == MTD_OPS_AUTO_OOB)
-		len = chip->ecc.layout->oobavail;
-	else
-		len = mtd->oobsize;
+	len = mtd_oobavail(mtd, ops);
 
 	if (unlikely(ops->ooboffs >= len)) {
 		pr_debug("%s: attempt to start read outside oob\n",
@@ -1840,11 +1989,12 @@
  * @chip: nand chip info structure
  * @buf: data buffer
  * @oob_required: must write chip->oob_poi to OOB
+ * @page: page number to write
  *
  * Not for syndrome calculating ECC controllers, which use a special oob layout.
  */
 static int nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
-				const uint8_t *buf, int oob_required)
+			       const uint8_t *buf, int oob_required, int page)
 {
 	chip->write_buf(mtd, buf, mtd->writesize);
 	if (oob_required)
@@ -1859,12 +2009,14 @@
  * @chip: nand chip info structure
  * @buf: data buffer
  * @oob_required: must write chip->oob_poi to OOB
+ * @page: page number to write
  *
  * We need a special oob layout and handling even when ECC isn't checked.
  */
 static int nand_write_page_raw_syndrome(struct mtd_info *mtd,
 					struct nand_chip *chip,
-					const uint8_t *buf, int oob_required)
+					const uint8_t *buf, int oob_required,
+					int page)
 {
 	int eccsize = chip->ecc.size;
 	int eccbytes = chip->ecc.bytes;
@@ -1901,9 +2053,11 @@
  * @chip: nand chip info structure
  * @buf: data buffer
  * @oob_required: must write chip->oob_poi to OOB
+ * @page: page number to write
  */
 static int nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
-				  const uint8_t *buf, int oob_required)
+				 const uint8_t *buf, int oob_required,
+				 int page)
 {
 	int i, eccsize = chip->ecc.size;
 	int eccbytes = chip->ecc.bytes;
@@ -1919,7 +2073,7 @@
 	for (i = 0; i < chip->ecc.total; i++)
 		chip->oob_poi[eccpos[i]] = ecc_calc[i];
 
-	return chip->ecc.write_page_raw(mtd, chip, buf, 1);
+	return chip->ecc.write_page_raw(mtd, chip, buf, 1, page);
 }
 
 /**
@@ -1928,9 +2082,11 @@
  * @chip: nand chip info structure
  * @buf: data buffer
  * @oob_required: must write chip->oob_poi to OOB
+ * @page: page number to write
  */
 static int nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
-				  const uint8_t *buf, int oob_required)
+				  const uint8_t *buf, int oob_required,
+				  int page)
 {
 	int i, eccsize = chip->ecc.size;
 	int eccbytes = chip->ecc.bytes;
@@ -1962,11 +2118,12 @@
  * @data_len:	data length
  * @buf:	data buffer
  * @oob_required: must write chip->oob_poi to OOB
+ * @page: page number to write
  */
 static int nand_write_subpage_hwecc(struct mtd_info *mtd,
 				struct nand_chip *chip, uint32_t offset,
 				uint32_t data_len, const uint8_t *buf,
-				int oob_required)
+				int oob_required, int page)
 {
 	uint8_t *oob_buf  = chip->oob_poi;
 	uint8_t *ecc_calc = chip->buffers->ecccalc;
@@ -2021,13 +2178,15 @@
  * @chip: nand chip info structure
  * @buf: data buffer
  * @oob_required: must write chip->oob_poi to OOB
+ * @page: page number to write
  *
  * The hw generator calculates the error syndrome automatically. Therefore we
  * need a special oob layout and handling.
  */
 static int nand_write_page_syndrome(struct mtd_info *mtd,
 				    struct nand_chip *chip,
-				    const uint8_t *buf, int oob_required)
+				    const uint8_t *buf, int oob_required,
+				    int page)
 {
 	int i, eccsize = chip->ecc.size;
 	int eccbytes = chip->ecc.bytes;
@@ -2091,12 +2250,13 @@
 
 	if (unlikely(raw))
 		status = chip->ecc.write_page_raw(mtd, chip, buf,
-							oob_required);
+						  oob_required, page);
 	else if (subpage)
 		status = chip->ecc.write_subpage(mtd, chip, offset, data_len,
-							 buf, oob_required);
+						 buf, oob_required, page);
 	else
-		status = chip->ecc.write_page(mtd, chip, buf, oob_required);
+		status = chip->ecc.write_page(mtd, chip, buf, oob_required,
+					      page);
 
 	if (status < 0)
 		return status;
@@ -2139,7 +2299,7 @@
 static uint8_t *nand_fill_oob(struct mtd_info *mtd, uint8_t *oob, size_t len,
 			      struct mtd_oob_ops *ops)
 {
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 
 	/*
 	 * Initialise to all 0xFF, to avoid the possibility of left over OOB
@@ -2199,12 +2359,11 @@
 			     struct mtd_oob_ops *ops)
 {
 	int chipnr, realpage, page, blockmask, column;
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 	uint32_t writelen = ops->len;
 
 	uint32_t oobwritelen = ops->ooblen;
-	uint32_t oobmaxlen = ops->mode == MTD_OPS_AUTO_OOB ?
-				mtd->oobavail : mtd->oobsize;
+	uint32_t oobmaxlen = mtd_oobavail(mtd, ops);
 
 	uint8_t *oob = ops->oobbuf;
 	uint8_t *buf = ops->datbuf;
@@ -2328,7 +2487,7 @@
 static int panic_nand_write(struct mtd_info *mtd, loff_t to, size_t len,
 			    size_t *retlen, const uint8_t *buf)
 {
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 	struct mtd_oob_ops ops;
 	int ret;
 
@@ -2388,15 +2547,12 @@
 			     struct mtd_oob_ops *ops)
 {
 	int chipnr, page, status, len;
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 
 	pr_debug("%s: to = 0x%08x, len = %i\n",
 			 __func__, (unsigned int)to, (int)ops->ooblen);
 
-	if (ops->mode == MTD_OPS_AUTO_OOB)
-		len = chip->ecc.layout->oobavail;
-	else
-		len = mtd->oobsize;
+	len = mtd_oobavail(mtd, ops);
 
 	/* Do not allow write past end of page */
 	if ((ops->ooboffs + ops->ooblen) > len) {
@@ -2513,7 +2669,7 @@
  */
 static int single_erase(struct mtd_info *mtd, int page)
 {
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 	/* Send commands to erase a block */
 	chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
 	chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1);
@@ -2545,7 +2701,7 @@
 		    int allowbbt)
 {
 	int page, status, pages_per_block, ret, chipnr;
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 	loff_t len;
 
 	pr_debug("%s: start = 0x%012llx, len = %llu\n",
@@ -2586,7 +2742,7 @@
 
 		/* Check if we have a bad block, we do not erase bad blocks! */
 		if (!instr->scrub && nand_block_checkbad(mtd, ((loff_t) page) <<
-					chip->page_shift, 0, allowbbt)) {
+					chip->page_shift, allowbbt)) {
 			pr_warn("%s: attempt to erase a bad block at page 0x%08x\n",
 				    __func__, page);
 			instr->state = MTD_ERASE_FAILED;
@@ -2673,7 +2829,20 @@
  */
 static int nand_block_isbad(struct mtd_info *mtd, loff_t offs)
 {
-	return nand_block_checkbad(mtd, offs, 1, 0);
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	int chipnr = (int)(offs >> chip->chip_shift);
+	int ret;
+
+	/* Select the NAND device */
+	nand_get_device(mtd, FL_READING);
+	chip->select_chip(mtd, chipnr);
+
+	ret = nand_block_checkbad(mtd, offs, 0);
+
+	chip->select_chip(mtd, -1);
+	nand_release_device(mtd);
+
+	return ret;
 }
 
 /**
@@ -2745,9 +2914,6 @@
 		return -EINVAL;
 #endif
 
-	/* clear the sub feature parameters */
-	memset(subfeature_param, 0, ONFI_SUBFEATURE_PARAM_LEN);
-
 	chip->cmdfunc(mtd, NAND_CMD_GET_FEATURES, addr, -1);
 	for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i)
 		*subfeature_param++ = chip->read_byte(mtd);
@@ -2908,7 +3074,7 @@
 
 static int nand_setup_read_retry_micron(struct mtd_info *mtd, int retry_mode)
 {
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 	uint8_t feature[ONFI_SUBFEATURE_PARAM_LEN] = {retry_mode};
 
 	return chip->onfi_set_features(mtd, chip, ONFI_FEATURE_ADDR_READ_RETRY,
@@ -3480,7 +3646,7 @@
 			if (find_full_id_nand(mtd, chip, type, id_data, &busw))
 				goto ident_done;
 		} else if (*dev_id == type->dev_id) {
-				break;
+			break;
 		}
 	}
 
@@ -3503,10 +3669,7 @@
 
 	chip->chipsize = (uint64_t)type->chipsize << 20;
 
-	if (!type->pagesize && chip->init_size) {
-		/* Set the pagesize, oobsize, erasesize by the driver */
-		busw = chip->init_size(mtd, chip, id_data);
-	} else if (!type->pagesize) {
+	if (!type->pagesize) {
 		/* Decode parameters from extended ID */
 		nand_decode_ext_id(mtd, chip, id_data, &busw);
 	} else {
@@ -3610,13 +3773,12 @@
  * This is the first phase of the normal nand_scan() function. It reads the
  * flash ID and sets up MTD fields accordingly.
  *
- * The mtd->owner field must be set to the module of the caller.
  */
 int nand_scan_ident(struct mtd_info *mtd, int maxchips,
 		    struct nand_flash_dev *table)
 {
 	int i, nand_maf_id, nand_dev_id;
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 	struct nand_flash_dev *type;
 
 	/* Set the default functions */
@@ -3680,7 +3842,7 @@
  */
 static bool nand_ecc_strength_good(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 	struct nand_ecc_ctrl *ecc = &chip->ecc;
 	int corr, ds_corr;
 
@@ -3709,7 +3871,7 @@
 int nand_scan_tail(struct mtd_info *mtd)
 {
 	int i;
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 	struct nand_ecc_ctrl *ecc = &chip->ecc;
 	struct nand_buffers *nbuf;
 
@@ -3786,7 +3948,7 @@
 			ecc->write_oob = nand_write_oob_std;
 		if (!ecc->read_subpage)
 			ecc->read_subpage = nand_read_subpage;
-		if (!ecc->write_subpage)
+		if (!ecc->write_subpage && ecc->hwctl && ecc->calculate)
 			ecc->write_subpage = nand_write_subpage_hwecc;
 
 	case NAND_ECC_HW_SYNDROME:
@@ -3864,10 +4026,8 @@
 		}
 
 		/* See nand_bch_init() for details. */
-		ecc->bytes = DIV_ROUND_UP(
-				ecc->strength * fls(8 * ecc->size), 8);
-		ecc->priv = nand_bch_init(mtd, ecc->size, ecc->bytes,
-					       &ecc->layout);
+		ecc->bytes = 0;
+		ecc->priv = nand_bch_init(mtd);
 		if (!ecc->priv) {
 			pr_warn("BCH ECC initialization failed!\n");
 			BUG();
@@ -3902,11 +4062,11 @@
 	 * The number of bytes available for a client to place data into
 	 * the out of band area.
 	 */
-	ecc->layout->oobavail = 0;
-	for (i = 0; ecc->layout->oobfree[i].length
-			&& i < ARRAY_SIZE(ecc->layout->oobfree); i++)
-		ecc->layout->oobavail += ecc->layout->oobfree[i].length;
-	mtd->oobavail = ecc->layout->oobavail;
+	mtd->oobavail = 0;
+	if (ecc->layout) {
+		for (i = 0; ecc->layout->oobfree[i].length; i++)
+			mtd->oobavail += ecc->layout->oobfree[i].length;
+	}
 
 	/* ECC sanity check: warn if it's too weak */
 	if (!nand_ecc_strength_good(mtd))
@@ -3991,18 +4151,6 @@
 }
 EXPORT_SYMBOL(nand_scan_tail);
 
-/*
- * is_module_text_address() isn't exported, and it's mostly a pointless
- * test if this is a module _anyway_ -- they'd have to try _really_ hard
- * to call us from in-kernel code if the core NAND support is modular.
- */
-#ifdef MODULE
-#define caller_is_module() (1)
-#else
-#define caller_is_module() \
-	is_module_text_address((unsigned long)__builtin_return_address(0))
-#endif
-
 /**
  * nand_scan - [NAND Interface] Scan for the NAND device
  * @mtd: MTD device structure
@@ -4010,19 +4158,12 @@
  *
  * This fills out all the uninitialized function pointers with the defaults.
  * The flash ID is read and the mtd/chip structures are filled with the
- * appropriate values. The mtd->owner field must be set to the module of the
- * caller.
+ * appropriate values.
  */
 int nand_scan(struct mtd_info *mtd, int maxchips)
 {
 	int ret;
 
-	/* Many callers got this wrong, so check for it for a while... */
-	if (!mtd->owner && caller_is_module()) {
-		pr_crit("%s called with NULL mtd->owner!\n", __func__);
-		BUG();
-	}
-
 	ret = nand_scan_ident(mtd, maxchips, NULL);
 	if (!ret)
 		ret = nand_scan_tail(mtd);
@@ -4030,9 +4171,6 @@
 }
 EXPORT_SYMBOL(nand_scan);
 
-module_init(nand_base_init);
-module_exit(nand_base_exit);
-
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Steven J. Hill <sjhill@realitydiluted.com>");
 MODULE_AUTHOR("Thomas Gleixner <tglx@linutronix.de>");
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index 00f28a4..74c4c9a 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -1,6 +1,4 @@
 /*
- *  drivers/mtd/nand_bbt.c
- *
  *  Overview:
  *   Bad block table support for the NAND driver
  *
@@ -65,7 +63,6 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/bbm.h>
 #include <linux/mtd/nand.h>
-#include <linux/mtd/nand_ecc.h>
 #include <linux/bitops.h>
 #include <linux/string.h>
 
@@ -173,7 +170,7 @@
 		struct nand_bbt_descr *td, int offs)
 {
 	int res, ret = 0, i, j, act = 0;
-	struct nand_chip *this = mtd->priv;
+	struct nand_chip *this = mtd_to_nand(mtd);
 	size_t retlen, len, totlen;
 	loff_t from;
 	int bits = td->options & NAND_BBT_NRBITS_MSK;
@@ -264,7 +261,7 @@
  */
 static int read_abs_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td, int chip)
 {
-	struct nand_chip *this = mtd->priv;
+	struct nand_chip *this = mtd_to_nand(mtd);
 	int res = 0, i;
 
 	if (td->options & NAND_BBT_PERCHIP) {
@@ -389,7 +386,7 @@
 static void read_abs_bbts(struct mtd_info *mtd, uint8_t *buf,
 			  struct nand_bbt_descr *td, struct nand_bbt_descr *md)
 {
-	struct nand_chip *this = mtd->priv;
+	struct nand_chip *this = mtd_to_nand(mtd);
 
 	/* Read the primary version, if available */
 	if (td->options & NAND_BBT_VERSION) {
@@ -455,7 +452,7 @@
 static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
 	struct nand_bbt_descr *bd, int chip)
 {
-	struct nand_chip *this = mtd->priv;
+	struct nand_chip *this = mtd_to_nand(mtd);
 	int i, numblocks, numpages;
 	int startblock;
 	loff_t from;
@@ -524,7 +521,7 @@
  */
 static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td)
 {
-	struct nand_chip *this = mtd->priv;
+	struct nand_chip *this = mtd_to_nand(mtd);
 	int i, chips;
 	int startblock, block, dir;
 	int scanlen = mtd->writesize + mtd->oobsize;
@@ -619,7 +616,7 @@
 		     struct nand_bbt_descr *td, struct nand_bbt_descr *md,
 		     int chipsel)
 {
-	struct nand_chip *this = mtd->priv;
+	struct nand_chip *this = mtd_to_nand(mtd);
 	struct erase_info einfo;
 	int i, res, chip = 0;
 	int bits, startblock, dir, page, offs, numblocks, sft, sftmsk;
@@ -718,7 +715,7 @@
 		/* Must we save the block contents? */
 		if (td->options & NAND_BBT_SAVECONTENT) {
 			/* Make it block aligned */
-			to &= ~((loff_t)((1 << this->bbt_erase_shift) - 1));
+			to &= ~(((loff_t)1 << this->bbt_erase_shift) - 1);
 			len = 1 << this->bbt_erase_shift;
 			res = mtd_read(mtd, to, len, &retlen, buf);
 			if (res < 0) {
@@ -820,7 +817,7 @@
  */
 static inline int nand_memory_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
 {
-	struct nand_chip *this = mtd->priv;
+	struct nand_chip *this = mtd_to_nand(mtd);
 
 	return create_bbt(mtd, this->buffers->databuf, bd, -1);
 }
@@ -839,7 +836,7 @@
 static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd)
 {
 	int i, chips, writeops, create, chipsel, res, res2;
-	struct nand_chip *this = mtd->priv;
+	struct nand_chip *this = mtd_to_nand(mtd);
 	struct nand_bbt_descr *td = this->bbt_td;
 	struct nand_bbt_descr *md = this->bbt_md;
 	struct nand_bbt_descr *rd, *rd2;
@@ -963,7 +960,7 @@
  */
 static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td)
 {
-	struct nand_chip *this = mtd->priv;
+	struct nand_chip *this = mtd_to_nand(mtd);
 	int i, j, chips, block, nrblocks, update;
 	uint8_t oldval;
 
@@ -1023,7 +1020,7 @@
  */
 static void verify_bbt_descr(struct mtd_info *mtd, struct nand_bbt_descr *bd)
 {
-	struct nand_chip *this = mtd->priv;
+	struct nand_chip *this = mtd_to_nand(mtd);
 	u32 pattern_len;
 	u32 bits;
 	u32 table_size;
@@ -1073,15 +1070,15 @@
  * The bad block table memory is allocated here. It must be freed by calling
  * the nand_free_bbt function.
  */
-int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
+static int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
 {
-	struct nand_chip *this = mtd->priv;
-	int len, res = 0;
+	struct nand_chip *this = mtd_to_nand(mtd);
+	int len, res;
 	uint8_t *buf;
 	struct nand_bbt_descr *td = this->bbt_td;
 	struct nand_bbt_descr *md = this->bbt_md;
 
-	len = mtd->size >> (this->bbt_erase_shift + 2);
+	len = (mtd->size >> (this->bbt_erase_shift + 2)) ? : 1;
 	/*
 	 * Allocate memory (2bit per block) and clear the memory bad block
 	 * table.
@@ -1097,10 +1094,9 @@
 	if (!td) {
 		if ((res = nand_memory_bbt(mtd, bd))) {
 			pr_err("nand_bbt: can't scan flash and build the RAM-based BBT\n");
-			kfree(this->bbt);
-			this->bbt = NULL;
+			goto err;
 		}
-		return res;
+		return 0;
 	}
 	verify_bbt_descr(mtd, td);
 	verify_bbt_descr(mtd, md);
@@ -1110,9 +1106,8 @@
 	len += (len >> this->page_shift) * mtd->oobsize;
 	buf = vmalloc(len);
 	if (!buf) {
-		kfree(this->bbt);
-		this->bbt = NULL;
-		return -ENOMEM;
+		res = -ENOMEM;
+		goto err;
 	}
 
 	/* Is the bbt at a given page? */
@@ -1124,6 +1119,8 @@
 	}
 
 	res = check_create(mtd, buf, bd);
+	if (res)
+		goto err;
 
 	/* Prevent the bbt regions from erasing / writing */
 	mark_bbt_region(mtd, td);
@@ -1131,6 +1128,11 @@
 		mark_bbt_region(mtd, md);
 
 	vfree(buf);
+	return 0;
+
+err:
+	kfree(this->bbt);
+	this->bbt = NULL;
 	return res;
 }
 
@@ -1143,7 +1145,7 @@
  */
 static int nand_update_bbt(struct mtd_info *mtd, loff_t offs)
 {
-	struct nand_chip *this = mtd->priv;
+	struct nand_chip *this = mtd_to_nand(mtd);
 	int len, res = 0;
 	int chip, chipsel;
 	uint8_t *buf;
@@ -1277,7 +1279,7 @@
  */
 int nand_default_bbt(struct mtd_info *mtd)
 {
-	struct nand_chip *this = mtd->priv;
+	struct nand_chip *this = mtd_to_nand(mtd);
 	int ret;
 
 	/* Is a flash based bad block table requested? */
@@ -1313,7 +1315,7 @@
  */
 int nand_isreserved_bbt(struct mtd_info *mtd, loff_t offs)
 {
-	struct nand_chip *this = mtd->priv;
+	struct nand_chip *this = mtd_to_nand(mtd);
 	int block;
 
 	block = (int)(offs >> this->bbt_erase_shift);
@@ -1328,7 +1330,7 @@
  */
 int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
 {
-	struct nand_chip *this = mtd->priv;
+	struct nand_chip *this = mtd_to_nand(mtd);
 	int block, res;
 
 	block = (int)(offs >> this->bbt_erase_shift);
@@ -1355,7 +1357,7 @@
  */
 int nand_markbad_bbt(struct mtd_info *mtd, loff_t offs)
 {
-	struct nand_chip *this = mtd->priv;
+	struct nand_chip *this = mtd_to_nand(mtd);
 	int block, ret = 0;
 
 	block = (int)(offs >> this->bbt_erase_shift);
@@ -1369,5 +1371,3 @@
 
 	return ret;
 }
-
-EXPORT_SYMBOL(nand_scan_bbt);
diff --git a/drivers/mtd/nand/nand_bch.c b/drivers/mtd/nand/nand_bch.c
index 35d2140..c145203 100644
--- a/drivers/mtd/nand/nand_bch.c
+++ b/drivers/mtd/nand/nand_bch.c
@@ -41,7 +41,7 @@
 int nand_bch_calculate_ecc(struct mtd_info *mtd, const unsigned char *buf,
 			   unsigned char *code)
 {
-	const struct nand_chip *chip = mtd->priv;
+	const struct nand_chip *chip = mtd_to_nand(mtd);
 	struct nand_bch_control *nbc = chip->ecc.priv;
 	unsigned int i;
 
@@ -67,7 +67,7 @@
 int nand_bch_correct_data(struct mtd_info *mtd, unsigned char *buf,
 			  unsigned char *read_ecc, unsigned char *calc_ecc)
 {
-	const struct nand_chip *chip = mtd->priv;
+	const struct nand_chip *chip = mtd_to_nand(mtd);
 	struct nand_bch_control *nbc = chip->ecc.priv;
 	unsigned int *errloc = nbc->errloc;
 	int i, count;
@@ -86,7 +86,7 @@
 		}
 	} else if (count < 0) {
 		printk(KERN_ERR "ecc unrecoverable error\n");
-		count = -1;
+		count = -EBADMSG;
 	}
 	return count;
 }
@@ -94,9 +94,6 @@
 /**
  * nand_bch_init - [NAND Interface] Initialize NAND BCH error correction
  * @mtd:	MTD block structure
- * @eccsize:	ecc block size in bytes
- * @eccbytes:	ecc length in bytes
- * @ecclayout:	output default layout
  *
  * Returns:
  *  a pointer to a new NAND BCH control structure, or NULL upon failure
@@ -110,14 +107,21 @@
  * @eccsize = 512  (thus, m=13 is the smallest integer such that 2^m-1 > 512*8)
  * @eccbytes = 7   (7 bytes are required to store m*t = 13*4 = 52 bits)
  */
-struct nand_bch_control *
-nand_bch_init(struct mtd_info *mtd, unsigned int eccsize, unsigned int eccbytes,
-	      struct nand_ecclayout **ecclayout)
+struct nand_bch_control *nand_bch_init(struct mtd_info *mtd)
 {
+	struct nand_chip *nand = mtd_to_nand(mtd);
 	unsigned int m, t, eccsteps, i;
-	struct nand_ecclayout *layout;
+	struct nand_ecclayout *layout = nand->ecc.layout;
 	struct nand_bch_control *nbc = NULL;
 	unsigned char *erased_page;
+	unsigned int eccsize = nand->ecc.size;
+	unsigned int eccbytes = nand->ecc.bytes;
+	unsigned int eccstrength = nand->ecc.strength;
+
+	if (!eccbytes && eccstrength) {
+		eccbytes = DIV_ROUND_UP(eccstrength * fls(8 * eccsize), 8);
+		nand->ecc.bytes = eccbytes;
+	}
 
 	if (!eccsize || !eccbytes) {
 		printk(KERN_WARNING "ecc parameters not supplied\n");
@@ -145,7 +149,7 @@
 	eccsteps = mtd->writesize/eccsize;
 
 	/* if no ecc placement scheme was provided, build one */
-	if (!*ecclayout) {
+	if (!layout) {
 
 		/* handle large page devices only */
 		if (mtd->oobsize < 64) {
@@ -171,7 +175,7 @@
 		layout->oobfree[0].offset = 2;
 		layout->oobfree[0].length = mtd->oobsize-2-layout->eccbytes;
 
-		*ecclayout = layout;
+		nand->ecc.layout = layout;
 	}
 
 	/* sanity checks */
@@ -179,7 +183,7 @@
 		printk(KERN_WARNING "eccsize %u is too large\n", eccsize);
 		goto fail;
 	}
-	if ((*ecclayout)->eccbytes != (eccsteps*eccbytes)) {
+	if (layout->eccbytes != (eccsteps*eccbytes)) {
 		printk(KERN_WARNING "invalid ecc layout\n");
 		goto fail;
 	}
@@ -203,6 +207,9 @@
 	for (i = 0; i < eccbytes; i++)
 		nbc->eccmask[i] ^= 0xff;
 
+	if (!eccstrength)
+		nand->ecc.strength = (eccbytes * 8) / fls(8 * eccsize);
+
 	return nbc;
 fail:
 	nand_bch_free(nbc);
diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c
index fdd0074..561d2cd 100644
--- a/drivers/mtd/nand/nand_ids.c
+++ b/drivers/mtd/nand/nand_ids.c
@@ -1,6 +1,4 @@
 /*
- *  drivers/mtd/nandids.c
- *
  *  Copyright (C) 2002 Thomas Gleixner (tglx@linutronix.de)
  *
  * This program is free software; you can redistribute it and/or modify
@@ -41,6 +39,10 @@
 	 * listed by full ID. We list them first so that we can easily identify
 	 * the most specific match.
 	 */
+	{"TC58NVG0S3E 1G 3.3V 8-bit",
+		{ .id = {0x98, 0xd1, 0x90, 0x15, 0x76, 0x14, 0x01, 0x00} },
+		  SZ_2K, SZ_128, SZ_128K, 0, 8, 64, NAND_ECC_INFO(1, SZ_512),
+		  2 },
 	{"TC58NVG2S0F 4G 3.3V 8-bit",
 		{ .id = {0x98, 0xdc, 0x90, 0x26, 0x76, 0x15, 0x01, 0x08} },
 		  SZ_4K, SZ_512, SZ_256K, 0, 8, 224, NAND_ECC_INFO(4, SZ_512) },
@@ -58,8 +60,8 @@
 		  SZ_16K, SZ_8K, SZ_4M, 0, 6, 1280, NAND_ECC_INFO(40, SZ_1K) },
 	{"H27UCG8T2ATR-BC 64G 3.3V 8-bit",
 		{ .id = {0xad, 0xde, 0x94, 0xda, 0x74, 0xc4} },
-		  SZ_8K, SZ_8K, SZ_2M, 0, 6, 640, NAND_ECC_INFO(40, SZ_1K),
-		  4 },
+		  SZ_8K, SZ_8K, SZ_2M, NAND_NEED_SCRAMBLING, 6, 640,
+		  NAND_ECC_INFO(40, SZ_1K), 4 },
 
 	LEGACY_ID_NAND("NAND 4MiB 5V 8-bit",   0x6B, 4, SZ_8K, SP_OPTIONS),
 	LEGACY_ID_NAND("NAND 4MiB 3,3V 8-bit", 0xE3, 4, SZ_8K, SP_OPTIONS),
diff --git a/drivers/mtd/nand/nand_plat.c b/drivers/mtd/nand/nand_plat.c
index 37a0206..335c3e3 100644
--- a/drivers/mtd/nand/nand_plat.c
+++ b/drivers/mtd/nand/nand_plat.c
@@ -25,7 +25,7 @@
 
 static void plat_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 {
-	struct nand_chip *this = mtd->priv;
+	struct nand_chip *this = mtd_to_nand(mtd);
 
 	if (cmd == NAND_CMD_NONE)
 		return;
@@ -39,7 +39,7 @@
 #ifdef NAND_PLAT_DEV_READY
 static int plat_dev_ready(struct mtd_info *mtd)
 {
-	return NAND_PLAT_DEV_READY((struct nand_chip *)mtd->priv);
+	return NAND_PLAT_DEV_READY((struct nand_chip *)mtd_to_nand(mtd));
 }
 #else
 # define plat_dev_ready NULL
diff --git a/drivers/mtd/nand/nand_spl_simple.c b/drivers/mtd/nand/nand_spl_simple.c
index e69f662..b023e00 100644
--- a/drivers/mtd/nand/nand_spl_simple.c
+++ b/drivers/mtd/nand/nand_spl_simple.c
@@ -11,7 +11,7 @@
 #include <linux/mtd/nand_ecc.h>
 
 static int nand_ecc_pos[] = CONFIG_SYS_NAND_ECCPOS;
-static nand_info_t mtd;
+static struct mtd_info *mtd;
 static struct nand_chip nand_chip;
 
 #define ECCSTEPS	(CONFIG_SYS_NAND_PAGE_SIZE / \
@@ -26,32 +26,32 @@
 static int nand_command(int block, int page, uint32_t offs,
 	u8 cmd)
 {
-	struct nand_chip *this = mtd.priv;
+	struct nand_chip *this = mtd_to_nand(mtd);
 	int page_addr = page + block * CONFIG_SYS_NAND_PAGE_COUNT;
 
-	while (!this->dev_ready(&mtd))
+	while (!this->dev_ready(mtd))
 		;
 
 	/* Begin command latch cycle */
-	this->cmd_ctrl(&mtd, cmd, NAND_CTRL_CLE | NAND_CTRL_CHANGE);
+	this->cmd_ctrl(mtd, cmd, NAND_CTRL_CLE | NAND_CTRL_CHANGE);
 	/* Set ALE and clear CLE to start address cycle */
 	/* Column address */
-	this->cmd_ctrl(&mtd, offs, NAND_CTRL_ALE | NAND_CTRL_CHANGE);
-	this->cmd_ctrl(&mtd, page_addr & 0xff, NAND_CTRL_ALE); /* A[16:9] */
-	this->cmd_ctrl(&mtd, (page_addr >> 8) & 0xff,
+	this->cmd_ctrl(mtd, offs, NAND_CTRL_ALE | NAND_CTRL_CHANGE);
+	this->cmd_ctrl(mtd, page_addr & 0xff, NAND_CTRL_ALE); /* A[16:9] */
+	this->cmd_ctrl(mtd, (page_addr >> 8) & 0xff,
 		       NAND_CTRL_ALE); /* A[24:17] */
 #ifdef CONFIG_SYS_NAND_4_ADDR_CYCLE
 	/* One more address cycle for devices > 32MiB */
-	this->cmd_ctrl(&mtd, (page_addr >> 16) & 0x0f,
+	this->cmd_ctrl(mtd, (page_addr >> 16) & 0x0f,
 		       NAND_CTRL_ALE); /* A[28:25] */
 #endif
 	/* Latch in address */
-	this->cmd_ctrl(&mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
+	this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
 
 	/*
 	 * Wait a while for the data to be ready
 	 */
-	while (!this->dev_ready(&mtd))
+	while (!this->dev_ready(mtd))
 		;
 
 	return 0;
@@ -63,12 +63,12 @@
 static int nand_command(int block, int page, uint32_t offs,
 	u8 cmd)
 {
-	struct nand_chip *this = mtd.priv;
+	struct nand_chip *this = mtd_to_nand(mtd);
 	int page_addr = page + block * CONFIG_SYS_NAND_PAGE_COUNT;
 	void (*hwctrl)(struct mtd_info *mtd, int cmd,
 			unsigned int ctrl) = this->cmd_ctrl;
 
-	while (!this->dev_ready(&mtd))
+	while (!this->dev_ready(mtd))
 		;
 
 	/* Emulate NAND_CMD_READOOB */
@@ -82,30 +82,30 @@
 		offs >>= 1;
 
 	/* Begin command latch cycle */
-	hwctrl(&mtd, cmd, NAND_CTRL_CLE | NAND_CTRL_CHANGE);
+	hwctrl(mtd, cmd, NAND_CTRL_CLE | NAND_CTRL_CHANGE);
 	/* Set ALE and clear CLE to start address cycle */
 	/* Column address */
-	hwctrl(&mtd, offs & 0xff,
-		       NAND_CTRL_ALE | NAND_CTRL_CHANGE); /* A[7:0] */
-	hwctrl(&mtd, (offs >> 8) & 0xff, NAND_CTRL_ALE); /* A[11:9] */
+	hwctrl(mtd, offs & 0xff,
+		    NAND_CTRL_ALE | NAND_CTRL_CHANGE); /* A[7:0] */
+	hwctrl(mtd, (offs >> 8) & 0xff, NAND_CTRL_ALE); /* A[11:9] */
 	/* Row address */
-	hwctrl(&mtd, (page_addr & 0xff), NAND_CTRL_ALE); /* A[19:12] */
-	hwctrl(&mtd, ((page_addr >> 8) & 0xff),
-		       NAND_CTRL_ALE); /* A[27:20] */
+	hwctrl(mtd, (page_addr & 0xff), NAND_CTRL_ALE); /* A[19:12] */
+	hwctrl(mtd, ((page_addr >> 8) & 0xff),
+		    NAND_CTRL_ALE); /* A[27:20] */
 #ifdef CONFIG_SYS_NAND_5_ADDR_CYCLE
 	/* One more address cycle for devices > 128MiB */
-	hwctrl(&mtd, (page_addr >> 16) & 0x0f,
+	hwctrl(mtd, (page_addr >> 16) & 0x0f,
 		       NAND_CTRL_ALE); /* A[31:28] */
 #endif
 	/* Latch in address */
-	hwctrl(&mtd, NAND_CMD_READSTART,
-		       NAND_CTRL_CLE | NAND_CTRL_CHANGE);
-	hwctrl(&mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
+	hwctrl(mtd, NAND_CMD_READSTART,
+		    NAND_CTRL_CLE | NAND_CTRL_CHANGE);
+	hwctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
 
 	/*
 	 * Wait a while for the data to be ready
 	 */
-	while (!this->dev_ready(&mtd))
+	while (!this->dev_ready(mtd))
 		;
 
 	return 0;
@@ -114,7 +114,7 @@
 
 static int nand_is_bad_block(int block)
 {
-	struct nand_chip *this = mtd.priv;
+	struct nand_chip *this = mtd_to_nand(mtd);
 	u_char bb_data[2];
 
 	nand_command(block, 0, CONFIG_SYS_NAND_BAD_BLOCK_POS,
@@ -124,11 +124,11 @@
 	 * Read one byte (or two if it's a 16 bit chip).
 	 */
 	if (this->options & NAND_BUSWIDTH_16) {
-		this->read_buf(&mtd, bb_data, 2);
+		this->read_buf(mtd, bb_data, 2);
 		if (bb_data[0] != 0xff || bb_data[1] != 0xff)
 			return 1;
 	} else {
-		this->read_buf(&mtd, bb_data, 1);
+		this->read_buf(mtd, bb_data, 1);
 		if (bb_data[0] != 0xff)
 			return 1;
 	}
@@ -139,7 +139,7 @@
 #if defined(CONFIG_SYS_NAND_HW_ECC_OOBFIRST)
 static int nand_read_page(int block, int page, uchar *dst)
 {
-	struct nand_chip *this = mtd.priv;
+	struct nand_chip *this = mtd_to_nand(mtd);
 	u_char ecc_calc[ECCTOTAL];
 	u_char ecc_code[ECCTOTAL];
 	u_char oob_data[CONFIG_SYS_NAND_OOBSIZE];
@@ -150,7 +150,7 @@
 	uint8_t *p = dst;
 
 	nand_command(block, page, 0, NAND_CMD_READOOB);
-	this->read_buf(&mtd, oob_data, CONFIG_SYS_NAND_OOBSIZE);
+	this->read_buf(mtd, oob_data, CONFIG_SYS_NAND_OOBSIZE);
 	nand_command(block, page, 0, NAND_CMD_READ0);
 
 	/* Pick the ECC bytes out of the oob data */
@@ -159,10 +159,10 @@
 
 
 	for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
-		this->ecc.hwctl(&mtd, NAND_ECC_READ);
-		this->read_buf(&mtd, p, eccsize);
-		this->ecc.calculate(&mtd, p, &ecc_calc[i]);
-		this->ecc.correct(&mtd, p, &ecc_code[i], &ecc_calc[i]);
+		this->ecc.hwctl(mtd, NAND_ECC_READ);
+		this->read_buf(mtd, p, eccsize);
+		this->ecc.calculate(mtd, p, &ecc_calc[i]);
+		this->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
 	}
 
 	return 0;
@@ -170,7 +170,7 @@
 #else
 static int nand_read_page(int block, int page, void *dst)
 {
-	struct nand_chip *this = mtd.priv;
+	struct nand_chip *this = mtd_to_nand(mtd);
 	u_char ecc_calc[ECCTOTAL];
 	u_char ecc_code[ECCTOTAL];
 	u_char oob_data[CONFIG_SYS_NAND_OOBSIZE];
@@ -184,11 +184,11 @@
 
 	for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
 		if (this->ecc.mode != NAND_ECC_SOFT)
-			this->ecc.hwctl(&mtd, NAND_ECC_READ);
-		this->read_buf(&mtd, p, eccsize);
-		this->ecc.calculate(&mtd, p, &ecc_calc[i]);
+			this->ecc.hwctl(mtd, NAND_ECC_READ);
+		this->read_buf(mtd, p, eccsize);
+		this->ecc.calculate(mtd, p, &ecc_calc[i]);
 	}
-	this->read_buf(&mtd, oob_data, CONFIG_SYS_NAND_OOBSIZE);
+	this->read_buf(mtd, oob_data, CONFIG_SYS_NAND_OOBSIZE);
 
 	/* Pick the ECC bytes out of the oob data */
 	for (i = 0; i < ECCTOTAL; i++)
@@ -202,7 +202,7 @@
 		 * from correct_data(). We just hope that all possible errors
 		 * are corrected by this routine.
 		 */
-		this->ecc.correct(&mtd, p, &ecc_code[i], &ecc_calc[i]);
+		this->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
 	}
 
 	return 0;
@@ -249,7 +249,7 @@
 	/*
 	 * Init board specific nand support
 	 */
-	mtd.priv = &nand_chip;
+	mtd = &nand_chip.mtd;
 	nand_chip.IO_ADDR_R = nand_chip.IO_ADDR_W =
 		(void  __iomem *)CONFIG_SYS_NAND_BASE;
 	board_nand_init(&nand_chip);
@@ -262,12 +262,12 @@
 #endif
 
 	if (nand_chip.select_chip)
-		nand_chip.select_chip(&mtd, 0);
+		nand_chip.select_chip(mtd, 0);
 }
 
 /* Unselect after operation */
 void nand_deselect(void)
 {
 	if (nand_chip.select_chip)
-		nand_chip.select_chip(&mtd, -1);
+		nand_chip.select_chip(mtd, -1);
 }
diff --git a/drivers/mtd/nand/nand_util.c b/drivers/mtd/nand/nand_util.c
index 71285b6..5bba66a 100644
--- a/drivers/mtd/nand/nand_util.c
+++ b/drivers/mtd/nand/nand_util.c
@@ -42,25 +42,26 @@
  * nand_erase_opts: - erase NAND flash with support for various options
  *		      (jffs2 formatting)
  *
- * @param meminfo	NAND device to erase
+ * @param mtd		nand mtd instance to erase
  * @param opts		options,  @see struct nand_erase_options
  * @return		0 in case of success
  *
  * This code is ported from flash_eraseall.c from Linux mtd utils by
  * Arcom Control System Ltd.
  */
-int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts)
+int nand_erase_opts(struct mtd_info *mtd,
+		    const nand_erase_options_t *opts)
 {
 	struct jffs2_unknown_node cleanmarker;
 	erase_info_t erase;
 	unsigned long erase_length, erased_length; /* in blocks */
 	int result;
 	int percent_complete = -1;
-	const char *mtd_device = meminfo->name;
+	const char *mtd_device = mtd->name;
 	struct mtd_oob_ops oob_opts;
-	struct nand_chip *chip = meminfo->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 
-	if ((opts->offset & (meminfo->erasesize - 1)) != 0) {
+	if ((opts->offset & (mtd->erasesize - 1)) != 0) {
 		printf("Attempt to erase non block-aligned data\n");
 		return -1;
 	}
@@ -68,11 +69,11 @@
 	memset(&erase, 0, sizeof(erase));
 	memset(&oob_opts, 0, sizeof(oob_opts));
 
-	erase.mtd = meminfo;
-	erase.len  = meminfo->erasesize;
+	erase.mtd = mtd;
+	erase.len = mtd->erasesize;
 	erase.addr = opts->offset;
-	erase_length = lldiv(opts->length + meminfo->erasesize - 1,
-			     meminfo->erasesize);
+	erase_length = lldiv(opts->length + mtd->erasesize - 1,
+			     mtd->erasesize);
 
 	cleanmarker.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
 	cleanmarker.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER);
@@ -97,7 +98,7 @@
 
 	for (erased_length = 0;
 	     erased_length < erase_length;
-	     erase.addr += meminfo->erasesize) {
+	     erase.addr += mtd->erasesize) {
 
 		WATCHDOG_RESET();
 
@@ -106,7 +107,7 @@
 			return -EFBIG;
 		}
 		if (!opts->scrub) {
-			int ret = mtd_block_isbad(meminfo, erase.addr);
+			int ret = mtd_block_isbad(mtd, erase.addr);
 			if (ret > 0) {
 				if (!opts->quiet)
 					printf("\rSkipping bad block at  "
@@ -129,7 +130,7 @@
 
 		erased_length++;
 
-		result = mtd_erase(meminfo, &erase);
+		result = mtd_erase(mtd, &erase);
 		if (result != 0) {
 			printf("\n%s: MTD Erase failure: %d\n",
 			       mtd_device, result);
@@ -145,9 +146,7 @@
 			ops.ooboffs = 0;
 			ops.mode = MTD_OPS_AUTO_OOB;
 
-			result = mtd_write_oob(meminfo,
-						    erase.addr,
-						    &ops);
+			result = mtd_write_oob(mtd, erase.addr, &ops);
 			if (result != 0) {
 				printf("\n%s: MTD writeoob failure: %d\n",
 				       mtd_device, result);
@@ -218,7 +217,7 @@
 {
 	int ret = 0;
 	int status;
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 
 	/* select the NAND device */
 	chip->select_chip(mtd, 0);
@@ -268,7 +267,7 @@
 	int ret = 0;
 	int chipnr;
 	int page;
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 
 	/* select the NAND device */
 	chipnr = (int)(offset >> chip->chip_shift);
@@ -303,7 +302,7 @@
  * @param mtd		nand mtd instance
  * @param start		start byte address
  * @param length	number of bytes to unlock (must be a multiple of
- *			page size nand->writesize)
+ *			page size mtd->writesize)
  * @param allexcept	if set, unlock everything not selected
  *
  * @return		0 on success, -1 in case of error
@@ -315,7 +314,7 @@
 	int chipnr;
 	int status;
 	int page;
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 
 	debug("nand_unlock%s: start: %08llx, length: %zd!\n",
 		allexcept ? " (allexcept)" : "", start, length);
@@ -399,7 +398,7 @@
  * Check if there are any bad blocks, and whether length including bad
  * blocks fits into device
  *
- * @param nand NAND device
+ * @param mtd nand mtd instance
  * @param offset offset in flash
  * @param length image length
  * @param used length of flash needed for the requested length
@@ -407,8 +406,8 @@
  *         1 if the image fits, but there are bad blocks
  *        -1 if the image does not fit
  */
-static int check_skip_len(nand_info_t *nand, loff_t offset, size_t length,
-		size_t *used)
+static int check_skip_len(struct mtd_info *mtd, loff_t offset, size_t length,
+			  size_t *used)
 {
 	size_t len_excl_bad = 0;
 	int ret = 0;
@@ -417,14 +416,14 @@
 		size_t block_len, block_off;
 		loff_t block_start;
 
-		if (offset >= nand->size)
+		if (offset >= mtd->size)
 			return -1;
 
-		block_start = offset & ~(loff_t)(nand->erasesize - 1);
-		block_off = offset & (nand->erasesize - 1);
-		block_len = nand->erasesize - block_off;
+		block_start = offset & ~(loff_t)(mtd->erasesize - 1);
+		block_off = offset & (mtd->erasesize - 1);
+		block_len = mtd->erasesize - block_off;
 
-		if (!nand_block_isbad(nand, block_start))
+		if (!nand_block_isbad(mtd, block_start))
 			len_excl_bad += block_len;
 		else
 			ret = 1;
@@ -441,7 +440,7 @@
 }
 
 #ifdef CONFIG_CMD_NAND_TRIMFFS
-static size_t drop_ffs(const nand_info_t *nand, const u_char *buf,
+static size_t drop_ffs(const struct mtd_info *mtd, const u_char *buf,
 			const size_t *len)
 {
 	size_t l = *len;
@@ -453,8 +452,8 @@
 
 	/* The resulting length must be aligned to the minimum flash I/O size */
 	l = i + 1;
-	l = (l + nand->writesize - 1) / nand->writesize;
-	l *=  nand->writesize;
+	l = (l + mtd->writesize - 1) / mtd->writesize;
+	l *=  mtd->writesize;
 
 	/*
 	 * since the input length may be unaligned, prevent access past the end
@@ -471,16 +470,17 @@
  * Reads page of NAND and verifies the contents and OOB against the
  * values in ops.
  *
- * @param nand		NAND device
+ * @param mtd		nand mtd instance
  * @param ops		MTD operations, including data to verify
  * @param ofs		offset in flash
  * @return		0 in case of success
  */
-int nand_verify_page_oob(nand_info_t *nand, struct mtd_oob_ops *ops, loff_t ofs)
+int nand_verify_page_oob(struct mtd_info *mtd, struct mtd_oob_ops *ops,
+			 loff_t ofs)
 {
 	int rval;
 	struct mtd_oob_ops vops;
-	size_t verlen = nand->writesize + nand->oobsize;
+	size_t verlen = mtd->writesize + mtd->oobsize;
 
 	memcpy(&vops, ops, sizeof(vops));
 
@@ -489,9 +489,9 @@
 	if (!vops.datbuf)
 		return -ENOMEM;
 
-	vops.oobbuf = vops.datbuf + nand->writesize;
+	vops.oobbuf = vops.datbuf + mtd->writesize;
 
-	rval = mtd_read_oob(nand, ofs, &vops);
+	rval = mtd_read_oob(mtd, ofs, &vops);
 	if (!rval)
 		rval = memcmp(ops->datbuf, vops.datbuf, vops.len);
 	if (!rval)
@@ -510,17 +510,17 @@
  * the contents of a buffer.  The offset into the NAND must be
  * page-aligned, and the function doesn't handle skipping bad blocks.
  *
- * @param nand		NAND device
+ * @param mtd		nand mtd instance
  * @param ofs		offset in flash
  * @param len		buffer length
  * @param buf		buffer to read from
  * @return		0 in case of success
  */
-int nand_verify(nand_info_t *nand, loff_t ofs, size_t len, u_char *buf)
+int nand_verify(struct mtd_info *mtd, loff_t ofs, size_t len, u_char *buf)
 {
 	int rval = 0;
 	size_t verofs;
-	size_t verlen = nand->writesize;
+	size_t verlen = mtd->writesize;
 	uint8_t *verbuf = memalign(ARCH_DMA_MINALIGN, verlen);
 
 	if (!verbuf)
@@ -529,8 +529,8 @@
 	/* Read the NAND back in page-size groups to limit malloc size */
 	for (verofs = ofs; verofs < ofs + len;
 	     verofs += verlen, buf += verlen) {
-		verlen = min(nand->writesize, (uint32_t)(ofs + len - verofs));
-		rval = nand_read(nand, verofs, &verlen, verbuf);
+		verlen = min(mtd->writesize, (uint32_t)(ofs + len - verofs));
+		rval = nand_read(mtd, verofs, &verlen, verbuf);
 		if (!rval || (rval == -EUCLEAN))
 			rval = memcmp(buf, verbuf, verlen);
 
@@ -558,7 +558,7 @@
  * beyond the limit we are passed, length is set to 0 and actual is set
  * to the required length.
  *
- * @param nand  	NAND device
+ * @param mtd		nand mtd instance
  * @param offset	offset in flash
  * @param length	buffer length
  * @param actual	set to size required to write length worth of
@@ -569,8 +569,8 @@
  * @param flags		flags modifying the behaviour of the write to NAND
  * @return		0 in case of success
  */
-int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
-		size_t *actual, loff_t lim, u_char *buffer, int flags)
+int nand_write_skip_bad(struct mtd_info *mtd, loff_t offset, size_t *length,
+			size_t *actual, loff_t lim, u_char *buffer, int flags)
 {
 	int rval = 0, blocksize;
 	size_t left_to_write = *length;
@@ -581,7 +581,7 @@
 	if (actual)
 		*actual = 0;
 
-	blocksize = nand->erasesize;
+	blocksize = mtd->erasesize;
 
 	/*
 	 * nand_write() handles unaligned, partial page writes.
@@ -594,13 +594,13 @@
 	 * you should only start a block skipping access at a
 	 * partition boundary).  So don't try to handle that.
 	 */
-	if ((offset & (nand->writesize - 1)) != 0) {
+	if ((offset & (mtd->writesize - 1)) != 0) {
 		printf("Attempt to write non page-aligned data\n");
 		*length = 0;
 		return -EINVAL;
 	}
 
-	need_skip = check_skip_len(nand, offset, *length, &used_for_write);
+	need_skip = check_skip_len(mtd, offset, *length, &used_for_write);
 
 	if (actual)
 		*actual = used_for_write;
@@ -618,10 +618,10 @@
 	}
 
 	if (!need_skip && !(flags & WITH_DROP_FFS)) {
-		rval = nand_write(nand, offset, length, buffer);
+		rval = nand_write(mtd, offset, length, buffer);
 
 		if ((flags & WITH_WR_VERIFY) && !rval)
-			rval = nand_verify(nand, offset, *length, buffer);
+			rval = nand_verify(mtd, offset, *length, buffer);
 
 		if (rval == 0)
 			return 0;
@@ -633,15 +633,15 @@
 	}
 
 	while (left_to_write > 0) {
-		size_t block_offset = offset & (nand->erasesize - 1);
+		size_t block_offset = offset & (mtd->erasesize - 1);
 		size_t write_size, truncated_write_size;
 
 		WATCHDOG_RESET();
 
-		if (nand_block_isbad(nand, offset & ~(nand->erasesize - 1))) {
+		if (nand_block_isbad(mtd, offset & ~(mtd->erasesize - 1))) {
 			printf("Skip bad block 0x%08llx\n",
-				offset & ~(nand->erasesize - 1));
-			offset += nand->erasesize - block_offset;
+				offset & ~(mtd->erasesize - 1));
+			offset += mtd->erasesize - block_offset;
 			continue;
 		}
 
@@ -653,15 +653,15 @@
 		truncated_write_size = write_size;
 #ifdef CONFIG_CMD_NAND_TRIMFFS
 		if (flags & WITH_DROP_FFS)
-			truncated_write_size = drop_ffs(nand, p_buffer,
+			truncated_write_size = drop_ffs(mtd, p_buffer,
 					&write_size);
 #endif
 
-		rval = nand_write(nand, offset, &truncated_write_size,
+		rval = nand_write(mtd, offset, &truncated_write_size,
 				p_buffer);
 
 		if ((flags & WITH_WR_VERIFY) && !rval)
-			rval = nand_verify(nand, offset,
+			rval = nand_verify(mtd, offset,
 				truncated_write_size, p_buffer);
 
 		offset += write_size;
@@ -693,7 +693,7 @@
  * the limit we are passed, length is set to 0 and actual is set to the
  * required length.
  *
- * @param nand NAND device
+ * @param mtd nand mtd instance
  * @param offset offset in flash
  * @param length buffer length, on return holds number of read bytes
  * @param actual set to size required to read length worth of buffer or 0
@@ -703,8 +703,8 @@
  * @param buffer buffer to write to
  * @return 0 in case of success
  */
-int nand_read_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
-		size_t *actual, loff_t lim, u_char *buffer)
+int nand_read_skip_bad(struct mtd_info *mtd, loff_t offset, size_t *length,
+		       size_t *actual, loff_t lim, u_char *buffer)
 {
 	int rval;
 	size_t left_to_read = *length;
@@ -712,7 +712,7 @@
 	u_char *p_buffer = buffer;
 	int need_skip;
 
-	if ((offset & (nand->writesize - 1)) != 0) {
+	if ((offset & (mtd->writesize - 1)) != 0) {
 		printf("Attempt to read non page-aligned data\n");
 		*length = 0;
 		if (actual)
@@ -720,7 +720,7 @@
 		return -EINVAL;
 	}
 
-	need_skip = check_skip_len(nand, offset, *length, &used_for_read);
+	need_skip = check_skip_len(mtd, offset, *length, &used_for_read);
 
 	if (actual)
 		*actual = used_for_read;
@@ -738,7 +738,7 @@
 	}
 
 	if (!need_skip) {
-		rval = nand_read(nand, offset, length, buffer);
+		rval = nand_read(mtd, offset, length, buffer);
 		if (!rval || rval == -EUCLEAN)
 			return 0;
 
@@ -749,24 +749,24 @@
 	}
 
 	while (left_to_read > 0) {
-		size_t block_offset = offset & (nand->erasesize - 1);
+		size_t block_offset = offset & (mtd->erasesize - 1);
 		size_t read_length;
 
 		WATCHDOG_RESET();
 
-		if (nand_block_isbad(nand, offset & ~(nand->erasesize - 1))) {
+		if (nand_block_isbad(mtd, offset & ~(mtd->erasesize - 1))) {
 			printf("Skipping bad block 0x%08llx\n",
-				offset & ~(nand->erasesize - 1));
-			offset += nand->erasesize - block_offset;
+				offset & ~(mtd->erasesize - 1));
+			offset += mtd->erasesize - block_offset;
 			continue;
 		}
 
-		if (left_to_read < (nand->erasesize - block_offset))
+		if (left_to_read < (mtd->erasesize - block_offset))
 			read_length = left_to_read;
 		else
-			read_length = nand->erasesize - block_offset;
+			read_length = mtd->erasesize - block_offset;
 
-		rval = nand_read(nand, offset, &read_length, p_buffer);
+		rval = nand_read(mtd, offset, &read_length, p_buffer);
 		if (rval && rval != -EUCLEAN) {
 			printf("NAND read from offset %llx failed %d\n",
 				offset, rval);
@@ -812,57 +812,57 @@
  * This is useful to determine if a block that caused a write error is still
  * good or should be marked as bad.
  *
- * @param nand NAND device
+ * @param mtd nand mtd instance
  * @param offset offset in flash
  * @return 0 if the block is still good
  */
-int nand_torture(nand_info_t *nand, loff_t offset)
+int nand_torture(struct mtd_info *mtd, loff_t offset)
 {
 	u_char patterns[] = {0xa5, 0x5a, 0x00};
 	struct erase_info instr = {
 		.mtd = nand,
 		.addr = offset,
-		.len = nand->erasesize,
+		.len = mtd->erasesize,
 	};
 	size_t retlen;
 	int err, ret = -1, i, patt_count;
 	u_char *buf;
 
-	if ((offset & (nand->erasesize - 1)) != 0) {
+	if ((offset & (mtd->erasesize - 1)) != 0) {
 		puts("Attempt to torture a block at a non block-aligned offset\n");
 		return -EINVAL;
 	}
 
-	if (offset + nand->erasesize > nand->size) {
+	if (offset + mtd->erasesize > mtd->size) {
 		puts("Attempt to torture a block outside the flash area\n");
 		return -EINVAL;
 	}
 
 	patt_count = ARRAY_SIZE(patterns);
 
-	buf = malloc_cache_aligned(nand->erasesize);
+	buf = malloc_cache_aligned(mtd->erasesize);
 	if (buf == NULL) {
 		puts("Out of memory for erase block buffer\n");
 		return -ENOMEM;
 	}
 
 	for (i = 0; i < patt_count; i++) {
-		err = nand->erase(nand, &instr);
+		err = mtd_erase(mtd, &instr);
 		if (err) {
 			printf("%s: erase() failed for block at 0x%llx: %d\n",
-				nand->name, instr.addr, err);
+				mtd->name, instr.addr, err);
 			goto out;
 		}
 
 		/* Make sure the block contains only 0xff bytes */
-		err = nand->read(nand, offset, nand->erasesize, &retlen, buf);
-		if ((err && err != -EUCLEAN) || retlen != nand->erasesize) {
+		err = mtd_read(mtd, offset, mtd->erasesize, &retlen, buf);
+		if ((err && err != -EUCLEAN) || retlen != mtd->erasesize) {
 			printf("%s: read() failed for block at 0x%llx: %d\n",
-				nand->name, instr.addr, err);
+				mtd->name, instr.addr, err);
 			goto out;
 		}
 
-		err = check_pattern(buf, 0xff, nand->erasesize);
+		err = check_pattern(buf, 0xff, mtd->erasesize);
 		if (!err) {
 			printf("Erased block at 0x%llx, but a non-0xff byte was found\n",
 				offset);
@@ -871,22 +871,22 @@
 		}
 
 		/* Write a pattern and check it */
-		memset(buf, patterns[i], nand->erasesize);
-		err = nand->write(nand, offset, nand->erasesize, &retlen, buf);
-		if (err || retlen != nand->erasesize) {
+		memset(buf, patterns[i], mtd->erasesize);
+		err = mtd_write(mtd, offset, mtd->erasesize, &retlen, buf);
+		if (err || retlen != mtd->erasesize) {
 			printf("%s: write() failed for block at 0x%llx: %d\n",
-				nand->name, instr.addr, err);
+				mtd->name, instr.addr, err);
 			goto out;
 		}
 
-		err = nand->read(nand, offset, nand->erasesize, &retlen, buf);
-		if ((err && err != -EUCLEAN) || retlen != nand->erasesize) {
+		err = mtd_read(mtd, offset, mtd->erasesize, &retlen, buf);
+		if ((err && err != -EUCLEAN) || retlen != mtd->erasesize) {
 			printf("%s: read() failed for block at 0x%llx: %d\n",
-				nand->name, instr.addr, err);
+				mtd->name, instr.addr, err);
 			goto out;
 		}
 
-		err = check_pattern(buf, patterns[i], nand->erasesize);
+		err = check_pattern(buf, patterns[i], mtd->erasesize);
 		if (!err) {
 			printf("Pattern 0x%.2x checking failed for block at "
 					"0x%llx\n", patterns[i], offset);
diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c
index 8a68cb0..0a9849e 100644
--- a/drivers/mtd/nand/ndfc.c
+++ b/drivers/mtd/nand/ndfc.c
@@ -1,6 +1,6 @@
 /*
  * Overview:
- *   Platform independend driver for NDFC (NanD Flash Controller)
+ *   Platform independent driver for NDFC (NanD Flash Controller)
  *   integrated into IBM/AMCC PPC4xx cores
  *
  * (C) Copyright 2006-2009
@@ -37,7 +37,7 @@
 
 static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 {
-	struct nand_chip *this = mtd->priv;
+	struct nand_chip *this = mtd_to_nand(mtd);
 	ulong base = (ulong) this->IO_ADDR_W & 0xffffff00;
 
 	if (cmd == NAND_CMD_NONE)
@@ -51,7 +51,7 @@
 
 static int ndfc_dev_ready(struct mtd_info *mtdinfo)
 {
-	struct nand_chip *this = mtdinfo->priv;
+	struct nand_chip *this = mtd_to_nand(mtdinfo);
 	ulong base = (ulong) this->IO_ADDR_W & 0xffffff00;
 
 	return (in_be32((u32 *)(base + NDFC_STAT)) & NDFC_STAT_IS_READY);
@@ -59,7 +59,7 @@
 
 static void ndfc_enable_hwecc(struct mtd_info *mtdinfo, int mode)
 {
-	struct nand_chip *this = mtdinfo->priv;
+	struct nand_chip *this = mtd_to_nand(mtdinfo);
 	ulong base = (ulong) this->IO_ADDR_W & 0xffffff00;
 	u32 ccr;
 
@@ -71,7 +71,7 @@
 static int ndfc_calculate_ecc(struct mtd_info *mtdinfo,
 			      const u_char *dat, u_char *ecc_code)
 {
-	struct nand_chip *this = mtdinfo->priv;
+	struct nand_chip *this = mtd_to_nand(mtdinfo);
 	ulong base = (ulong) this->IO_ADDR_W & 0xffffff00;
 	u32 ecc;
 	u8 *p = (u8 *)&ecc;
@@ -96,7 +96,7 @@
  */
 static void ndfc_read_buf(struct mtd_info *mtdinfo, uint8_t *buf, int len)
 {
-	struct nand_chip *this = mtdinfo->priv;
+	struct nand_chip *this = mtd_to_nand(mtdinfo);
 	ulong base = (ulong) this->IO_ADDR_W & 0xffffff00;
 	uint32_t *p = (uint32_t *) buf;
 
@@ -110,7 +110,7 @@
  */
 static void ndfc_write_buf(struct mtd_info *mtdinfo, const uint8_t *buf, int len)
 {
-	struct nand_chip *this = mtdinfo->priv;
+	struct nand_chip *this = mtd_to_nand(mtdinfo);
 	ulong base = (ulong) this->IO_ADDR_W & 0xffffff00;
 	uint32_t *p = (uint32_t *) buf;
 
@@ -124,7 +124,7 @@
 static uint8_t ndfc_read_byte(struct mtd_info *mtd)
 {
 
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 
 #ifdef CONFIG_SYS_NAND_BUSWIDTH_16BIT
 	return (uint8_t) readw(chip->IO_ADDR_R);
diff --git a/drivers/mtd/nand/omap_gpmc.c b/drivers/mtd/nand/omap_gpmc.c
index 6a45d28..37c4341 100644
--- a/drivers/mtd/nand/omap_gpmc.c
+++ b/drivers/mtd/nand/omap_gpmc.c
@@ -58,8 +58,8 @@
 static void omap_nand_hwcontrol(struct mtd_info *mtd, int32_t cmd,
 				uint32_t ctrl)
 {
-	register struct nand_chip *this = mtd->priv;
-	struct omap_nand_info *info = this->priv;
+	register struct nand_chip *this = mtd_to_nand(mtd);
+	struct omap_nand_info *info = nand_get_controller_data(this);
 	int cs = info->cs;
 
 	/*
@@ -85,8 +85,8 @@
 /* Check wait pin as dev ready indicator */
 static int omap_dev_ready(struct mtd_info *mtd)
 {
-	register struct nand_chip *this = mtd->priv;
-	struct omap_nand_info *info = this->priv;
+	register struct nand_chip *this = mtd_to_nand(mtd);
+	struct omap_nand_info *info = nand_get_controller_data(this);
 	return gpmc_cfg->status & (1 << (8 + info->ws));
 }
 
@@ -163,7 +163,7 @@
 				return 0;
 			printf("Error: Bad compare! failed\n");
 			/* detected 2 bit error */
-			return -1;
+			return -EBADMSG;
 		}
 	}
 	return 0;
@@ -177,8 +177,8 @@
 __maybe_unused
 static void omap_enable_hwecc(struct mtd_info *mtd, int32_t mode)
 {
-	struct nand_chip	*nand	= mtd->priv;
-	struct omap_nand_info	*info	= nand->priv;
+	struct nand_chip	*nand	= mtd_to_nand(mtd);
+	struct omap_nand_info	*info	= nand_get_controller_data(nand);
 	unsigned int dev_width = (nand->options & NAND_BUSWIDTH_16) ? 1 : 0;
 	unsigned int ecc_algo = 0;
 	unsigned int bch_type = 0;
@@ -262,8 +262,8 @@
 static int omap_calculate_ecc(struct mtd_info *mtd, const uint8_t *dat,
 				uint8_t *ecc_code)
 {
-	struct nand_chip *chip = mtd->priv;
-	struct omap_nand_info *info = chip->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct omap_nand_info *info = nand_get_controller_data(chip);
 	uint32_t *ptr, val = 0;
 	int8_t i = 0, j;
 
@@ -392,7 +392,7 @@
 {
 	int ret;
 	uint32_t cnt;
-	struct omap_nand_info *info = chip->priv;
+	struct omap_nand_info *info = nand_get_controller_data(chip);
 
 	ret = omap_prefetch_enable(PREFETCH_FIFOTHRESHOLD_MAX, len, 0, info->cs);
 	if (ret < 0)
@@ -417,7 +417,7 @@
 
 static inline void omap_nand_read(struct mtd_info *mtd, uint8_t *buf, int len)
 {
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 
 	if (chip->options & NAND_BUSWIDTH_16)
 		nand_read_buf16(mtd, buf, len);
@@ -429,7 +429,7 @@
 {
 	int ret;
 	uint32_t head, tail;
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 
 	/*
 	 * If the destination buffer is unaligned, start with reading
@@ -491,8 +491,8 @@
 static int omap_correct_data_bch(struct mtd_info *mtd, uint8_t *dat,
 				uint8_t *read_ecc, uint8_t *calc_ecc)
 {
-	struct nand_chip *chip = mtd->priv;
-	struct omap_nand_info *info = chip->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct omap_nand_info *info = nand_get_controller_data(chip);
 	struct nand_ecc_ctrl *ecc = &chip->ecc;
 	uint32_t error_count = 0, error_max;
 	uint32_t error_loc[ELM_MAX_ERROR_COUNT];
@@ -652,8 +652,8 @@
 	int i, count;
 	/* cannot correct more than 8 errors */
 	unsigned int errloc[8];
-	struct nand_chip *chip = mtd->priv;
-	struct omap_nand_info *info = chip->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct omap_nand_info *info = nand_get_controller_data(chip);
 
 	count = decode_bch(info->control, NULL, 512, read_ecc, calc_ecc,
 							NULL, errloc);
@@ -691,8 +691,8 @@
  */
 static void __maybe_unused omap_free_bch(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd->priv;
-	struct omap_nand_info *info = chip->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct omap_nand_info *info = nand_get_controller_data(chip);
 
 	if (info->control) {
 		free_bch(info->control);
@@ -710,7 +710,7 @@
  */
 static int omap_select_ecc_scheme(struct nand_chip *nand,
 	enum omap_ecc ecc_scheme, unsigned int pagesize, unsigned int oobsize) {
-	struct omap_nand_info	*info		= nand->priv;
+	struct omap_nand_info	*info		= nand_get_controller_data(nand);
 	struct nand_ecclayout	*ecclayout	= &omap_ecclayout;
 	int eccsteps = pagesize / SECTOR_BYTES;
 	int i;
@@ -898,13 +898,13 @@
 
 	if (nand_curr_device < 0 ||
 	    nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE ||
-	    !nand_info[nand_curr_device].name) {
+	    !nand_info[nand_curr_device]->name) {
 		printf("nand: error: no NAND devices found\n");
 		return -ENODEV;
 	}
 
-	mtd = &nand_info[nand_curr_device];
-	nand = mtd->priv;
+	mtd = nand_info[nand_curr_device];
+	nand = mtd_to_nand(mtd);
 	nand->options |= NAND_OWN_BUFFERS;
 	nand->options &= ~NAND_SUBPAGE_READ;
 	/* Setup the ecc configurations again */
@@ -994,7 +994,7 @@
 	omap_nand_info[cs].control = NULL;
 	omap_nand_info[cs].cs = cs;
 	omap_nand_info[cs].ws = wscfg[cs];
-	nand->priv	= &omap_nand_info[cs];
+	nand_set_controller_data(nand, &omap_nand_info[cs]);
 	nand->cmd_ctrl	= omap_nand_hwcontrol;
 	nand->options	|= NAND_NO_PADDING | NAND_CACHEPRG;
 	nand->chip_delay = 100;
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index d529467..d3ac539 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -900,7 +900,8 @@
 static void nand_cmdfunc(struct mtd_info *mtd, unsigned command,
 			 int column, int page_addr)
 {
-	struct pxa3xx_nand_host *host = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct pxa3xx_nand_host *host = nand_get_controller_data(chip);
 	struct pxa3xx_nand_info *info = host->info_data;
 	int exec_cmd;
 
@@ -960,7 +961,8 @@
 				  const unsigned command,
 				  int column, int page_addr)
 {
-	struct pxa3xx_nand_host *host = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct pxa3xx_nand_host *host = nand_get_controller_data(chip);
 	struct pxa3xx_nand_info *info = host->info_data;
 	int exec_cmd, ext_cmd_type;
 
@@ -1079,7 +1081,8 @@
 }
 
 static int pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd,
-		struct nand_chip *chip, const uint8_t *buf, int oob_required)
+		struct nand_chip *chip, const uint8_t *buf, int oob_required,
+		int page)
 {
 	chip->write_buf(mtd, buf, mtd->writesize);
 	chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
@@ -1091,7 +1094,7 @@
 		struct nand_chip *chip, uint8_t *buf, int oob_required,
 		int page)
 {
-	struct pxa3xx_nand_host *host = mtd->priv;
+	struct pxa3xx_nand_host *host = nand_get_controller_data(chip);
 	struct pxa3xx_nand_info *info = host->info_data;
 
 	chip->read_buf(mtd, buf, mtd->writesize);
@@ -1117,7 +1120,8 @@
 
 static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
 {
-	struct pxa3xx_nand_host *host = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct pxa3xx_nand_host *host = nand_get_controller_data(chip);
 	struct pxa3xx_nand_info *info = host->info_data;
 	char retval = 0xFF;
 
@@ -1130,7 +1134,8 @@
 
 static u16 pxa3xx_nand_read_word(struct mtd_info *mtd)
 {
-	struct pxa3xx_nand_host *host = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct pxa3xx_nand_host *host = nand_get_controller_data(chip);
 	struct pxa3xx_nand_info *info = host->info_data;
 	u16 retval = 0xFFFF;
 
@@ -1143,7 +1148,8 @@
 
 static void pxa3xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 {
-	struct pxa3xx_nand_host *host = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct pxa3xx_nand_host *host = nand_get_controller_data(chip);
 	struct pxa3xx_nand_info *info = host->info_data;
 	int real_len = min_t(size_t, len, info->buf_count - info->buf_start);
 
@@ -1154,7 +1160,8 @@
 static void pxa3xx_nand_write_buf(struct mtd_info *mtd,
 		const uint8_t *buf, int len)
 {
-	struct pxa3xx_nand_host *host = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct pxa3xx_nand_host *host = nand_get_controller_data(chip);
 	struct pxa3xx_nand_info *info = host->info_data;
 	int real_len = min_t(size_t, len, info->buf_count - info->buf_start);
 
@@ -1169,7 +1176,8 @@
 
 static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this)
 {
-	struct pxa3xx_nand_host *host = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct pxa3xx_nand_host *host = nand_get_controller_data(chip);
 	struct pxa3xx_nand_info *info = host->info_data;
 
 	if (info->need_wait) {
@@ -1210,7 +1218,7 @@
 {
 	struct pxa3xx_nand_host *host = info->host[info->cs];
 	struct mtd_info *mtd = host->mtd;
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 
 	info->reg_ndcr |= (host->col_addr_cycles == 2) ? NDCR_RA_START : 0;
 	info->reg_ndcr |= (chip->page_shift == 6) ? NDCR_PG_PER_BLK : 0;
@@ -1262,7 +1270,7 @@
 	int ret;
 
 	mtd = info->host[info->cs]->mtd;
-	chip = mtd->priv;
+	chip = mtd_to_nand(mtd);
 
 	/* configure default flash values */
 	info->reg_ndcr = 0x0; /* enable all interrupts */
@@ -1354,10 +1362,10 @@
 
 static int pxa3xx_nand_scan(struct mtd_info *mtd)
 {
-	struct pxa3xx_nand_host *host = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct pxa3xx_nand_host *host = nand_get_controller_data(chip);
 	struct pxa3xx_nand_info *info = host->info_data;
 	struct pxa3xx_nand_platform_data *pdata = info->pdata;
-	struct nand_chip *chip = mtd->priv;
 	int ret;
 	uint16_t ecc_strength, ecc_step;
 
@@ -1477,16 +1485,15 @@
 
 	info->variant = pxa3xx_nand_get_variant();
 	for (cs = 0; cs < pdata->num_cs; cs++) {
-		mtd = &nand_info[cs];
 		chip = (struct nand_chip *)
 			((u8 *)&info[1] + sizeof(*host) * cs);
+		mtd = nand_to_mtd(chip);
 		host = (struct pxa3xx_nand_host *)chip;
 		info->host[cs] = host;
 		host->mtd = mtd;
 		host->cs = cs;
 		host->info_data = info;
 		host->read_id_bytes = 4;
-		mtd->priv = host;
 		mtd->owner = THIS_MODULE;
 
 		chip->ecc.read_page	= pxa3xx_nand_read_page_hwecc;
@@ -1573,8 +1580,10 @@
 			continue;
 		}
 
+		if (nand_register(cs, mtd))
+			continue;
+
-		if (!ret)
-			probe_success = 1;
+		probe_success = 1;
 	}
 
 	if (!probe_success)
@@ -1601,6 +1610,4 @@
 	ret = pxa3xx_nand_probe(info);
 	if (ret)
 		return;
-
-	nand_register(0);
 }
diff --git a/drivers/mtd/nand/s3c2410_nand.c b/drivers/mtd/nand/s3c2410_nand.c
index b3a2a60..dd742a6 100644
--- a/drivers/mtd/nand/s3c2410_nand.c
+++ b/drivers/mtd/nand/s3c2410_nand.c
@@ -31,7 +31,7 @@
 static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
 {
 	int i;
-	struct nand_chip *this = mtd->priv;
+	struct nand_chip *this = mtd_to_nand(mtd);
 
 	for (i = 0; i < len; i++)
 		buf[i] = readb(this->IO_ADDR_R);
@@ -40,7 +40,7 @@
 
 static void s3c24x0_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 {
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 	struct s3c24x0_nand *nand = s3c24x0_get_base_nand();
 
 	debug("hwcontrol(): 0x%02x 0x%02x\n", cmd, ctrl);
@@ -104,7 +104,7 @@
 		return 0;
 
 	printf("s3c24x0_nand_correct_data: not implemented\n");
-	return -1;
+	return -EBADMSG;
 }
 #endif
 
diff --git a/drivers/mtd/nand/tegra_nand.c b/drivers/mtd/nand/tegra_nand.c
index a77db7b..2032f65 100644
--- a/drivers/mtd/nand/tegra_nand.c
+++ b/drivers/mtd/nand/tegra_nand.c
@@ -143,10 +143,10 @@
  */
 static uint8_t read_byte(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 	struct nand_drv *info;
 
-	info = (struct nand_drv *)chip->priv;
+	info = (struct nand_drv *)nand_get_controller_data(chip);
 
 	writel(CMD_GO | CMD_PIO | CMD_RX | CMD_CE0 | CMD_A_VALID,
 	       &info->reg->command);
@@ -169,8 +169,8 @@
 {
 	int i, s;
 	unsigned int reg;
-	struct nand_chip *chip = mtd->priv;
-	struct nand_drv *info = (struct nand_drv *)chip->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_drv *info = (struct nand_drv *)nand_get_controller_data(chip);
 
 	for (i = 0; i < len; i += 4) {
 		s = (len - i) > 4 ? 4 : len - i;
@@ -194,11 +194,11 @@
  */
 static int nand_dev_ready(struct mtd_info *mtd)
 {
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 	int reg_val;
 	struct nand_drv *info;
 
-	info = (struct nand_drv *)chip->priv;
+	info = (struct nand_drv *)nand_get_controller_data(chip);
 
 	reg_val = readl(&info->reg->status);
 	if (reg_val & STATUS_RBSY0)
@@ -245,10 +245,10 @@
 static void nand_command(struct mtd_info *mtd, unsigned int command,
 	int column, int page_addr)
 {
-	struct nand_chip *chip = mtd->priv;
+	struct nand_chip *chip = mtd_to_nand(mtd);
 	struct nand_drv *info;
 
-	info = (struct nand_drv *)chip->priv;
+	info = (struct nand_drv *)nand_get_controller_data(chip);
 
 	/*
 	 * Write out the command to the device.
@@ -512,7 +512,7 @@
 		return -EINVAL;
 	}
 
-	info = (struct nand_drv *)chip->priv;
+	info = (struct nand_drv *)nand_get_controller_data(chip);
 	config = &info->config;
 	if (set_bus_width_page_size(config, &reg_val))
 		return -EINVAL;
@@ -657,16 +657,9 @@
  * @param buf	data buffer
  */
 static int nand_write_page_hwecc(struct mtd_info *mtd,
-	struct nand_chip *chip, const uint8_t *buf, int oob_required)
+	struct nand_chip *chip, const uint8_t *buf, int oob_required,
+	int page)
 {
-	int page;
-	struct nand_drv *info;
-
-	info = (struct nand_drv *)chip->priv;
-
-	page = (readl(&info->reg->addr_reg1) >> 16) |
-		(readl(&info->reg->addr_reg2) << 16);
-
 	nand_rw_page(mtd, chip, (uint8_t *)buf, page, 1, 1);
 	return 0;
 }
@@ -697,15 +690,9 @@
  * @param buf	data buffer
  */
 static int nand_write_page_raw(struct mtd_info *mtd,
-		struct nand_chip *chip,	const uint8_t *buf, int oob_required)
+		struct nand_chip *chip,	const uint8_t *buf,
+		int oob_required, int page)
 {
-	int page;
-	struct nand_drv *info;
-
-	info = (struct nand_drv *)chip->priv;
-	page = (readl(&info->reg->addr_reg1) >> 16) |
-		(readl(&info->reg->addr_reg2) << 16);
-
 	nand_rw_page(mtd, chip, (uint8_t *)buf, page, 0, 1);
 	return 0;
 }
@@ -734,7 +721,7 @@
 
 	if (((int)chip->oob_poi) & 0x03)
 		return -EINVAL;
-	info = (struct nand_drv *)chip->priv;
+	info = (struct nand_drv *)nand_get_controller_data(chip);
 	if (set_bus_width_page_size(&info->config, &reg_val))
 		return -EINVAL;
 
@@ -963,7 +950,7 @@
 	nand->ecc.strength = 1;
 	nand->select_chip = nand_select_chip;
 	nand->dev_ready  = nand_dev_ready;
-	nand->priv = &nand_ctrl;
+	nand_set_controller_data(nand, &nand_ctrl);
 
 	/* Disable subpage writes as we do not provide ecc->hwctl */
 	nand->options |= NAND_NO_SUBPAGE_WRITE;
@@ -976,8 +963,7 @@
 
 	dm_gpio_set_value(&config->wp_gpio, 1);
 
-	our_mtd = &nand_info[devnum];
-	our_mtd->priv = nand;
+	our_mtd = nand_to_mtd(nand);
 	ret = nand_scan_ident(our_mtd, CONFIG_SYS_NAND_MAX_CHIPS, NULL);
 	if (ret)
 		return ret;
@@ -989,7 +975,7 @@
 	if (ret)
 		return ret;
 
-	ret = nand_register(devnum);
+	ret = nand_register(devnum, our_mtd);
 	if (ret)
 		return ret;
 
diff --git a/drivers/mtd/nand/vf610_nfc.c b/drivers/mtd/nand/vf610_nfc.c
index 1faec5e..f99bdaf 100644
--- a/drivers/mtd/nand/vf610_nfc.c
+++ b/drivers/mtd/nand/vf610_nfc.c
@@ -146,7 +146,6 @@
 };
 
 struct vf610_nfc {
-	struct mtd_info *mtd;
 	struct nand_chip chip;
 	void __iomem *regs;
 	uint buf_offset;
@@ -155,8 +154,7 @@
 	enum vf610_nfc_alt_buf alt_buf;
 };
 
-#define mtd_to_nfc(_mtd) \
-	(struct vf610_nfc *)((struct nand_chip *)_mtd->priv)->priv
+#define mtd_to_nfc(_mtd) nand_get_controller_data(mtd_to_nand(_mtd))
 
 #if defined(CONFIG_SYS_NAND_VF610_NFC_45_ECC_BYTES)
 #define ECC_HW_MODE ECC_45_BYTE
@@ -608,7 +606,7 @@
  * ECC will be calculated automatically
  */
 static int vf610_nfc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
-			       const uint8_t *buf, int oob_required)
+			       const uint8_t *buf, int oob_required, int page)
 {
 	struct vf610_nfc *nfc = mtd_to_nfc(mtd);
 
@@ -630,7 +628,7 @@
 
 static int vf610_nfc_nand_init(int devnum, void __iomem *addr)
 {
-	struct mtd_info *mtd = &nand_info[devnum];
+	struct mtd_info *mtd;
 	struct nand_chip *chip;
 	struct vf610_nfc *nfc;
 	int err = 0;
@@ -653,8 +651,8 @@
 	chip = &nfc->chip;
 	nfc->regs = addr;
 
-	mtd->priv = chip;
-	chip->priv = nfc;
+	mtd = nand_to_mtd(chip);
+	nand_set_controller_data(chip, nfc);
 
 	if (cfg.width == 16)
 		chip->options |= NAND_BUSWIDTH_16;
@@ -753,7 +751,7 @@
 	if (err)
 		return err;
 
-	err = nand_register(devnum);
+	err = nand_register(devnum, mtd);
 	if (err)
 		return err;
 
diff --git a/drivers/mtd/spi/sf_params.c b/drivers/mtd/spi/sf_params.c
index 4f37e33..c577d9e 100644
--- a/drivers/mtd/spi/sf_params.c
+++ b/drivers/mtd/spi/sf_params.c
@@ -67,6 +67,7 @@
 	{"S25FL128S_64K",  0x012018, 0x4d01,    64 * 1024,   256, RD_FULL,		     WR_QPP},
 	{"S25FL256S_256K", 0x010219, 0x4d00,   256 * 1024,   128, RD_FULL,		     WR_QPP},
 	{"S25FL256S_64K",  0x010219, 0x4d01,	64 * 1024,   512, RD_FULL,		     WR_QPP},
+	{"S25FS512S",      0x010220, 0x4D00,   128 * 1024,   512, RD_FULL,                   WR_QPP},
 	{"S25FL512S_256K", 0x010220, 0x4d00,   256 * 1024,   256, RD_FULL,		     WR_QPP},
 	{"S25FL512S_64K",  0x010220, 0x4d01,    64 * 1024,  1024, RD_FULL,		     WR_QPP},
 	{"S25FL512S_512K", 0x010220, 0x4f00,   256 * 1024,   256, RD_FULL,		     WR_QPP},
diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index fa0e799..64d4e0f 100644
--- a/drivers/mtd/spi/spi_flash.c
+++ b/drivers/mtd/spi/spi_flash.c
@@ -1072,7 +1072,8 @@
 	 * sector that is not overlaid by the parameter sectors.
 	 * The uniform sector erase command has no effect on parameter sectors.
 	 */
-	if (jedec == 0x0219 && (ext_jedec & 0xff00) == 0x4d00) {
+	if ((jedec == 0x0219 || (jedec == 0x0220)) &&
+	    (ext_jedec & 0xff00) == 0x4d00) {
 		int ret;
 		u8 id[6];
 
@@ -1146,7 +1147,7 @@
 	 * have 256b pages.
 	 */
 	if (ext_jedec == 0x4d00) {
-		if ((jedec == 0x0215) || (jedec == 0x216))
+		if ((jedec == 0x0215) || (jedec == 0x216) || (jedec == 0x220))
 			flash->page_size = 256;
 		else
 			flash->page_size = 512;
diff --git a/drivers/net/fm/fm.c b/drivers/net/fm/fm.c
index e2a8ed3..00cdfd4 100644
--- a/drivers/net/fm/fm.c
+++ b/drivers/net/fm/fm.c
@@ -360,7 +360,7 @@
 	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(nand_info[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 f975fd8..fd130d5 100644
--- a/drivers/net/phy/cortina.c
+++ b/drivers/net/phy/cortina.c
@@ -139,8 +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,
-		       &fw_length, (u_char *)addr);
+	ret = nand_read(nand_info[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",
 		       CONFIG_CORTINA_FW_ADDR, ret);
diff --git a/drivers/pci/pcie_layerscape.c b/drivers/pci/pcie_layerscape.c
index 0ba960e..2e6b986 100644
--- a/drivers/pci/pcie_layerscape.c
+++ b/drivers/pci/pcie_layerscape.c
@@ -569,7 +569,7 @@
 	unsigned char header_type;
 	int index;
 	u32 streamid;
-	pci_dev_t dev;
+	pci_dev_t dev, bdf;
 	int bus;
 	unsigned short id;
 	struct pci_controller *hose;
@@ -611,12 +611,15 @@
 					continue;
 				}
 
+				/* the DT fixup must be relative to the hose first_busno */
+				bdf = dev - PCI_BDF(hose->first_busno, 0, 0);
+
 				/* map PCI b.d.f to streamID in LUT */
-				ls_pcie_lut_set_mapping(pcie, index, dev >> 8,
+				ls_pcie_lut_set_mapping(pcie, index, bdf >> 8,
 							streamid);
 
 				/* update msi-map in device tree */
-				fdt_pcie_set_msi_map_entry(blob, pcie, dev >> 8,
+				fdt_pcie_set_msi_map_entry(blob, pcie, bdf >> 8,
 							   streamid);
 			}
 		}
diff --git a/fs/jffs2/jffs2_1pass.c b/fs/jffs2/jffs2_1pass.c
index ba038b1..f771e94 100644
--- a/fs/jffs2/jffs2_1pass.c
+++ b/fs/jffs2/jffs2_1pass.c
@@ -195,7 +195,7 @@
 			}
 
 			retlen = NAND_CACHE_SIZE;
-			if (nand_read(&nand_info[id->num], nand_cache_off,
+			if (nand_read(nand_info[id->num], nand_cache_off,
 						&retlen, nand_cache) != 0 ||
 					retlen != NAND_CACHE_SIZE) {
 				printf("read_nand_cached: error reading nand off %#x size %d bytes\n",
diff --git a/fs/jffs2/jffs2_nand_1pass.c b/fs/jffs2/jffs2_nand_1pass.c
index 740f787..d94c48f 100644
--- a/fs/jffs2/jffs2_nand_1pass.c
+++ b/fs/jffs2/jffs2_nand_1pass.c
@@ -23,7 +23,7 @@
 # define DEBUGF(fmt,args...)
 #endif
 
-static nand_info_t *nand;
+static struct mtd_info *mtd;
 
 /* Compression names */
 static char *compr_names[] = {
@@ -304,7 +304,7 @@
 			len = sizeof(struct jffs2_raw_inode);
 			if (dest)
 				len += jNode->csize;
-			nand_read(nand, jNode->offset, &len, inode);
+			nand_read(mtd, jNode->offset, &len, inode);
 			/* ignore data behind latest known EOF */
 			if (inode->offset > totalSize)
 				continue;
@@ -450,7 +450,7 @@
 
 	if(!d || !i) return -1;
 	len = d->nsize;
-	nand_read(nand, d->offset + sizeof(struct jffs2_raw_dirent),
+	nand_read(mtd, d->offset + sizeof(struct jffs2_raw_dirent),
 		  &len, &fname);
 	fname[d->nsize] = '\0';
 
@@ -592,7 +592,9 @@
 	for (jNode = (struct b_inode *)pL->frag.listHead; jNode; jNode = jNode->next) {
 		if (jNode->ino == jDirFoundIno) {
 			size_t len = jNode->csize;
-			nand_read(nand, jNode->offset + sizeof(struct jffs2_raw_inode), &len, &tmp);
+			nand_read(mtd,
+				  jNode->offset + sizeof(struct jffs2_raw_inode),
+				  &len, &tmp);
 			tmp[jNode->csize] = '\0';
 			break;
 		}
@@ -760,14 +762,14 @@
 #endif
 
 static int
-jffs2_fill_scan_buf(nand_info_t *nand, unsigned char *buf,
+jffs2_fill_scan_buf(struct mtd_info *mtd, unsigned char *buf,
 		    unsigned ofs, unsigned len)
 {
 	int ret;
 	unsigned olen;
 
 	olen = len;
-	ret = nand_read(nand, ofs, &olen, buf);
+	ret = nand_read(mtd, ofs, &olen, buf);
 	if (ret) {
 		printf("nand_read(0x%x bytes from 0x%x) returned %d\n", len, ofs, ret);
 		return ret;
@@ -794,7 +796,7 @@
 	u32 counterN = 0;
 
 	struct mtdids *id = part->dev->id;
-	nand = nand_info + id->num;
+	mtd = nand_info[id->num];
 
 	/* if we are building a list we need to refresh the cache. */
 	jffs_init_1pass_list(part);
@@ -802,7 +804,7 @@
 	pL->partOffset = part->offset;
 	puts ("Scanning JFFS2 FS:   ");
 
-	sectorsize = nand->erasesize;
+	sectorsize = mtd->erasesize;
 	nr_blocks = part->size / sectorsize;
 	buf = malloc(sectorsize);
 	if (!buf)
@@ -813,10 +815,10 @@
 
 		offset = part->offset + i * sectorsize;
 
-		if (nand_block_isbad(nand, offset))
+		if (nand_block_isbad(mtd, offset))
 			continue;
 
-		if (jffs2_fill_scan_buf(nand, buf, offset, EMPTY_SCAN_SIZE))
+		if (jffs2_fill_scan_buf(mtd, buf, offset, EMPTY_SCAN_SIZE))
 			return 0;
 
 		ofs = 0;
@@ -826,7 +828,7 @@
 		if (ofs == EMPTY_SCAN_SIZE)
 			continue;
 
-		if (jffs2_fill_scan_buf(nand, buf + EMPTY_SCAN_SIZE, offset + EMPTY_SCAN_SIZE, sectorsize - EMPTY_SCAN_SIZE))
+		if (jffs2_fill_scan_buf(mtd, buf + EMPTY_SCAN_SIZE, offset + EMPTY_SCAN_SIZE, sectorsize - EMPTY_SCAN_SIZE))
 			return 0;
 		offset += ofs;
 
diff --git a/fs/yaffs2/yaffs_uboot_glue.c b/fs/yaffs2/yaffs_uboot_glue.c
index 50000a1..25aa6d1 100644
--- a/fs/yaffs2/yaffs_uboot_glue.c
+++ b/fs/yaffs2/yaffs_uboot_glue.c
@@ -141,8 +141,6 @@
 	}
 }
 
-extern nand_info_t nand_info[];
-
 void cmd_yaffs_tracemask(unsigned set, unsigned mask)
 {
 	if (set)
@@ -171,7 +169,7 @@
 	dev = calloc(1, sizeof(*dev));
 	mp = strdup(_mp);
 
-	mtd = &nand_info[flash_dev];
+	mtd = nand_info[flash_dev];
 
 	if (!dev || !mp) {
 		/* Alloc error */
@@ -192,7 +190,7 @@
 		goto err;
 	}
 
-	chip =  mtd->priv;
+	chip =  mtd_to_nand(mtd);
 
 	/* Check for any conflicts */
 	yaffs_dev_rewind();
@@ -260,9 +258,7 @@
 		dev = yaffs_next_dev();
 		if (!dev)
 			return;
-		flash_dev =
-			((unsigned) dev->driver_context - (unsigned) nand_info)/
-				sizeof(nand_info[0]);
+		flash_dev = nand_mtd_to_devnum(dev->driver_context);
 		printf("%-10s %5d 0x%05x 0x%05x %s",
 			dev->param.name, flash_dev,
 			dev->param.start_block, dev->param.end_block,
diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h
index f2810a1..0abcbe4 100644
--- a/include/asm-generic/global_data.h
+++ b/include/asm-generic/global_data.h
@@ -141,5 +141,6 @@
 #define GD_FLG_SPL_INIT		0x00400	/* spl_init() has been called	   */
 #define GD_FLG_SKIP_RELOC	0x00800	/* Don't relocate */
 #define GD_FLG_RECORD		0x01000	/* Record console */
+#define GD_FLG_ENV_DEFAULT	0x02000 /* Default variable flag */
 
 #endif /* __ASM_GENERIC_GBL_DATA_H */
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index 2500c10..4aa0004 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -251,6 +251,8 @@
 				int value);
 	int (*get_value)(struct udevice *dev, unsigned offset);
 	int (*set_value)(struct udevice *dev, unsigned offset, int value);
+	int (*get_open_drain)(struct udevice *dev, unsigned offset);
+	int (*set_open_drain)(struct udevice *dev, unsigned offset, int value);
 	/**
 	 * get_function() Get the GPIO function
 	 *
@@ -550,6 +552,38 @@
 int dm_gpio_set_value(const struct gpio_desc *desc, int value);
 
 /**
+ * dm_gpio_get_open_drain() - Check if open-drain-mode of a GPIO is active
+ *
+ * This checks if open-drain-mode for a GPIO is enabled or not. This method is
+ * optional.
+ *
+ * @desc:	GPIO description containing device, offset and flags,
+ *		previously returned by gpio_request_by_name()
+ * @return Value of open drain mode for GPIO (0 for inactive, 1 for active) or
+ *	   -ve on error
+ */
+int dm_gpio_get_open_drain(struct gpio_desc *desc);
+
+/**
+ * dm_gpio_set_open_drain() - Switch open-drain-mode of a GPIO on or off
+ *
+ * This enables or disables open-drain mode for a GPIO. This method is
+ * optional; if the driver does not support it, nothing happens when the method
+ * is called.
+ *
+ * In open-drain mode, instead of actively driving the output (Push-pull
+ * output), the GPIO's pin is connected to the collector (for a NPN transistor)
+ * or the drain (for a MOSFET) of a transistor, respectively. The pin then
+ * either forms an open circuit or a connection to ground, depending on the
+ * state of the transistor.
+ *
+ * @desc:	GPIO description containing device, offset and flags,
+ *		previously returned by gpio_request_by_name()
+ * @return 0 if OK, -ve on error
+ */
+int dm_gpio_set_open_drain(struct gpio_desc *desc, int value);
+
+/**
  * dm_gpio_set_dir() - Set the direction for a GPIO
  *
  * This sets up the direction according tot the provided flags. It will do
diff --git a/include/configs/ls1012a_common.h b/include/configs/ls1012a_common.h
new file mode 100644
index 0000000..ccd94ec
--- /dev/null
+++ b/include/configs/ls1012a_common.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2016 Freescale Semiconductor
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __LS1012A_COMMON_H
+#define __LS1012A_COMMON_H
+
+#define CONFIG_FSL_LAYERSCAPE
+#define CONFIG_FSL_LSCH2
+#define CONFIG_LS1012A
+#define CONFIG_GICV2
+
+#define	CONFIG_SYS_HAS_SERDES
+
+#include <asm/arch/config.h>
+#define CONFIG_SYS_NO_FLASH
+
+#define CONFIG_SUPPORT_RAW_INITRD
+
+#define CONFIG_DISPLAY_BOARDINFO_LATE
+
+#define CONFIG_SYS_TEXT_BASE		0x40100000
+
+#define CONFIG_SYS_FSL_CLK
+#define CONFIG_SYS_CLK_FREQ		100000000
+#define CONFIG_DDR_CLK_FREQ		125000000
+
+#define CONFIG_SKIP_LOWLEVEL_INIT
+#define CONFIG_BOARD_EARLY_INIT_F	1
+
+#define CONFIG_SYS_INIT_SP_ADDR		(CONFIG_SYS_FSL_OCRAM_BASE + 0xfff0)
+#define CONFIG_SYS_LOAD_ADDR	(CONFIG_SYS_DDR_SDRAM_BASE + 0x10000000)
+
+#define CONFIG_SYS_DDR_SDRAM_BASE	0x80000000
+#define CONFIG_SYS_FSL_DDR_SDRAM_BASE_PHY	0
+#define CONFIG_SYS_SDRAM_BASE		CONFIG_SYS_DDR_SDRAM_BASE
+
+/* Generic Timer Definitions */
+#define COUNTER_FREQUENCY		CONFIG_SYS_CLK_FREQ/4	/* 25MHz */
+
+/* CSU */
+#define CONFIG_LAYERSCAPE_NS_ACCESS
+
+/* Size of malloc() pool */
+#define CONFIG_SYS_MALLOC_LEN		(CONFIG_ENV_SIZE + 128 * 1024)
+
+/*SPI device */
+#ifdef CONFIG_QSPI_BOOT
+#define CONFIG_SYS_QE_FW_IN_SPIFLASH
+#define CONFIG_SYS_FMAN_FW_ADDR		0x400d0000
+#define CONFIG_ENV_SPI_BUS		0
+#define CONFIG_ENV_SPI_CS		0
+#define CONFIG_ENV_SPI_MAX_HZ		1000000
+#define CONFIG_ENV_SPI_MODE		0x03
+#define CONFIG_SPI_FLASH_SPANSION
+#define CONFIG_FSL_SPI_INTERFACE
+#define CONFIG_SF_DATAFLASH
+
+#define CONFIG_FSL_QSPI
+#define QSPI0_AMBA_BASE		0x40000000
+#define CONFIG_SPI_FLASH_SPANSION
+#define CONFIG_SPI_FLASH_BAR
+
+#define FSL_QSPI_FLASH_SIZE		(1 << 24)
+#define FSL_QSPI_FLASH_NUM		2
+
+/*
+ * Environment
+ */
+#define CONFIG_ENV_OVERWRITE
+
+#define CONFIG_ENV_IS_IN_SPI_FLASH
+#define CONFIG_ENV_SIZE			0x40000          /* 256KB */
+#define CONFIG_ENV_OFFSET		0x200000        /* 2MB */
+#define CONFIG_ENV_SECT_SIZE		0x40000
+#endif
+
+/* I2C */
+#define CONFIG_SYS_I2C
+#define CONFIG_SYS_I2C_MXC
+#define CONFIG_SYS_I2C_MXC_I2C1		/* enable I2C bus 1 */
+#define CONFIG_SYS_I2C_MXC_I2C2		/* enable I2C bus 2 */
+
+#define CONFIG_CONS_INDEX       1
+#define CONFIG_SYS_NS16550_SERIAL
+#define CONFIG_SYS_NS16550_REG_SIZE     1
+#define CONFIG_SYS_NS16550_CLK          (get_bus_freq(0)/2)
+
+#define CONFIG_BAUDRATE			115200
+#define CONFIG_SYS_BAUDRATE_TABLE	{ 9600, 19200, 38400, 57600, 115200 }
+
+/* Command line configuration */
+#define CONFIG_CMD_ENV
+#undef CONFIG_CMD_IMLS
+
+#define CONFIG_ARCH_EARLY_INIT_R
+
+#define CONFIG_SYS_HZ			1000
+
+#define CONFIG_HWCONFIG
+#define HWCONFIG_BUFFER_SIZE		128
+
+#define CONFIG_DISPLAY_CPUINFO
+
+/* Initial environment variables */
+#define CONFIG_EXTRA_ENV_SETTINGS		\
+	"initrd_high=0xffffffff\0"		\
+	"verify=no\0"				\
+	"hwconfig=fsl_ddr:bank_intlv=auto\0"	\
+	"loadaddr=0x80100000\0"			\
+	"kernel_addr=0x100000\0"		\
+	"ramdisk_addr=0x800000\0"		\
+	"ramdisk_size=0x2000000\0"		\
+	"fdt_high=0xffffffffffffffff\0"		\
+	"initrd_high=0xffffffffffffffff\0"	\
+	"kernel_start=0xa00000\0"		\
+	"kernel_load=0xa0000000\0"		\
+	"kernel_size=0x2800000\0"		\
+	"console=ttyAMA0,38400n8\0"
+
+#define CONFIG_BOOTARGS		"console=ttyS0,115200 root=/dev/ram0 " \
+				"earlycon=uart8250,mmio,0x21c0500"
+#define CONFIG_BOOTCOMMAND		"sf probe 0:0; sf read $kernel_load "\
+					"$kernel_start $kernel_size && "\
+					"bootm $kernel_load"
+#define CONFIG_BOOTDELAY		10
+
+/* Monitor Command Prompt */
+#define CONFIG_SYS_CBSIZE		512	/* Console I/O Buffer Size */
+#define CONFIG_SYS_PBSIZE		(CONFIG_SYS_CBSIZE + \
+					sizeof(CONFIG_SYS_PROMPT) + 16)
+#define CONFIG_SYS_BARGSIZE		CONFIG_SYS_CBSIZE /* Boot args buffer */
+#define CONFIG_SYS_LONGHELP
+#define CONFIG_CMDLINE_EDITING		1
+#define CONFIG_AUTO_COMPLETE
+#define CONFIG_SYS_MAXARGS		64	/* max command args */
+
+#define CONFIG_PANIC_HANG
+#define CONFIG_SYS_BOOTM_LEN   (64 << 20)      /* Increase max gunzip size */
+
+#include <asm/fsl_secure_boot.h>
+
+#endif /* __LS1012A_COMMON_H */
diff --git a/include/configs/ls1012afrdm.h b/include/configs/ls1012afrdm.h
new file mode 100644
index 0000000..ad81142
--- /dev/null
+++ b/include/configs/ls1012afrdm.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __LS1012ARDB_H__
+#define __LS1012ARDB_H__
+
+#include "ls1012a_common.h"
+
+#define CONFIG_DIMM_SLOTS_PER_CTLR	1
+#define CONFIG_CHIP_SELECTS_PER_CTRL	1
+#define CONFIG_NR_DRAM_BANKS		2
+#define CONFIG_SYS_SDRAM_SIZE		0x20000000
+
+#define CONFIG_SYS_MMDC_CORE_CONTROL_1		0x04180000
+#define CONFIG_SYS_MMDC_CORE_CONTROL_2		0x84180000
+
+#define CONFIG_CMD_MEMINFO
+#define CONFIG_CMD_MEMTEST
+#define CONFIG_SYS_MEMTEST_START	0x80000000
+#define CONFIG_SYS_MEMTEST_END		0x9fffffff
+
+/*
+* USB
+*/
+#define CONFIG_HAS_FSL_XHCI_USB
+
+#ifdef CONFIG_HAS_FSL_XHCI_USB
+#define CONFIG_USB_XHCI_FSL
+#define CONFIG_USB_MAX_CONTROLLER_COUNT         1
+#define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS      2
+#define CONFIG_USB_STORAGE
+#endif
+
+#define CONFIG_CMD_MEMINFO
+#define CONFIG_CMD_MEMTEST
+#define CONFIG_SYS_MEMTEST_START	0x80000000
+#define CONFIG_SYS_MEMTEST_END		0x9fffffff
+
+#endif /* __LS1012ARDB_H__ */
diff --git a/include/configs/ls1012aqds.h b/include/configs/ls1012aqds.h
new file mode 100644
index 0000000..fcf402c
--- /dev/null
+++ b/include/configs/ls1012aqds.h
@@ -0,0 +1,189 @@
+/*
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __LS1012AQDS_H__
+#define __LS1012AQDS_H__
+
+#include "ls1012a_common.h"
+
+
+#define CONFIG_DIMM_SLOTS_PER_CTLR	1
+#define CONFIG_CHIP_SELECTS_PER_CTRL	1
+#define CONFIG_NR_DRAM_BANKS		2
+#define CONFIG_SYS_SDRAM_SIZE		0x40000000
+
+#define CONFIG_SYS_MMDC_CORE_CONTROL_1		0x05180000
+#define CONFIG_SYS_MMDC_CORE_CONTROL_2		0x85180000
+
+/*
+ * QIXIS Definitions
+ */
+#define CONFIG_FSL_QIXIS
+
+#ifdef CONFIG_FSL_QIXIS
+#define CONFIG_QIXIS_I2C_ACCESS
+#define CONFIG_SYS_I2C_FPGA_ADDR	0x66
+#define QIXIS_LBMAP_BRDCFG_REG		0x04
+#define QIXIS_LBMAP_SWITCH		6
+#define QIXIS_LBMAP_MASK		0xf7
+#define QIXIS_LBMAP_SHIFT		0
+#define QIXIS_LBMAP_DFLTBANK		0x00
+#define QIXIS_LBMAP_ALTBANK		0x08
+#define QIXIS_RST_CTL_RESET		0x41
+#define QIXIS_RCFG_CTL_RECONFIG_IDLE	0x20
+#define QIXIS_RCFG_CTL_RECONFIG_START	0x21
+#define QIXIS_RCFG_CTL_WATCHDOG_ENBLE	0x08
+#endif
+
+/*
+ * I2C bus multiplexer
+ */
+#define I2C_MUX_PCA_ADDR_PRI		0x77
+#define I2C_MUX_PCA_ADDR_SEC		0x76 /* Secondary multiplexer */
+#define I2C_RETIMER_ADDR		0x18
+#define I2C_MUX_CH_DEFAULT		0x8
+#define I2C_MUX_CH_CH7301		0xC
+#define I2C_MUX_CH5			0xD
+#define I2C_MUX_CH7			0xF
+
+#define I2C_MUX_CH_VOL_MONITOR 0xa
+
+/*
+* RTC configuration
+*/
+#define RTC
+#define CONFIG_RTC_PCF8563 1
+#define CONFIG_SYS_I2C_RTC_ADDR         0x51  /* Channel 3*/
+#define CONFIG_CMD_DATE
+
+/* EEPROM */
+#define CONFIG_ID_EEPROM
+#define CONFIG_CMD_EEPROM
+#define CONFIG_SYS_I2C_EEPROM_NXID
+#define CONFIG_SYS_EEPROM_BUS_NUM    0
+#define CONFIG_SYS_I2C_EEPROM_ADDR   0x57
+#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN     1
+#define CONFIG_SYS_EEPROM_PAGE_WRITE_BITS 3
+#define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS 5
+
+
+/* Voltage monitor on channel 2*/
+#define I2C_VOL_MONITOR_ADDR           0x40
+#define I2C_VOL_MONITOR_BUS_V_OFFSET   0x2
+#define I2C_VOL_MONITOR_BUS_V_OVF      0x1
+#define I2C_VOL_MONITOR_BUS_V_SHIFT    3
+
+/* DSPI */
+#define CONFIG_FSL_DSPI1
+#define CONFIG_DEFAULT_SPI_BUS 1
+
+#define CONFIG_CMD_SPI
+#define MMAP_DSPI          DSPI1_BASE_ADDR
+
+#define CONFIG_SYS_DSPI_CTAR0   1
+
+#define CONFIG_SYS_DSPI_CTAR1	(DSPI_CTAR_TRSZ(7) | DSPI_CTAR_PCSSCK_1CLK |\
+				DSPI_CTAR_PASC(0) | DSPI_CTAR_PDT(0) | \
+				DSPI_CTAR_CSSCK(2) | DSPI_CTAR_ASC(0) | \
+				DSPI_CTAR_DT(0))
+#define CONFIG_SPI_FLASH_SST /* cs1 */
+
+#define CONFIG_SYS_DSPI_CTAR2	(DSPI_CTAR_TRSZ(7) | DSPI_CTAR_PCSSCK_1CLK |\
+				DSPI_CTAR_PASC(0) | DSPI_CTAR_PDT(0) | \
+				DSPI_CTAR_CSSCK(0) | DSPI_CTAR_ASC(0) | \
+				DSPI_CTAR_DT(0))
+#define CONFIG_SPI_FLASH_STMICRO /* cs2 */
+
+#define CONFIG_SYS_DSPI_CTAR3	(DSPI_CTAR_TRSZ(7) | DSPI_CTAR_PCSSCK_1CLK |\
+				DSPI_CTAR_PASC(0) | DSPI_CTAR_PDT(0) | \
+				DSPI_CTAR_CSSCK(2) | DSPI_CTAR_ASC(0) | \
+				DSPI_CTAR_DT(0))
+#define CONFIG_SPI_FLASH_EON /* cs3 */
+
+#define CONFIG_SF_DEFAULT_SPEED      10000000
+#define CONFIG_SF_DEFAULT_MODE       SPI_MODE_0
+#define CONFIG_SF_DEFAULT_BUS        1
+#define CONFIG_SF_DEFAULT_CS         0
+
+/*
+* USB
+*/
+/* EHCI Support - disbaled by default */
+/*#define CONFIG_HAS_FSL_DR_USB*/
+
+#ifdef CONFIG_HAS_FSL_DR_USB
+#define CONFIG_USB_EHCI
+#define CONFIG_USB_EHCI_FSL
+#define CONFIG_EHCI_HCD_INIT_AFTER_RESET
+#endif
+
+/*XHCI Support - enabled by default*/
+#define CONFIG_HAS_FSL_XHCI_USB
+
+#ifdef CONFIG_HAS_FSL_XHCI_USB
+#define CONFIG_USB_XHCI_FSL
+#define CONFIG_USB_MAX_CONTROLLER_COUNT         1
+#define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS      2
+#define CONFIG_USB_STORAGE
+#endif
+
+/*  MMC  */
+#define CONFIG_MMC
+#ifdef CONFIG_MMC
+#define CONFIG_FSL_ESDHC
+#define CONFIG_SYS_FSL_MMC_HAS_CAPBLT_VS33
+#define CONFIG_GENERIC_MMC
+#define CONFIG_DOS_PARTITION
+#endif
+
+/* SATA */
+#define CONFIG_LIBATA
+#define	CONFIG_SCSI
+#define CONFIG_SCSI_AHCI
+#define CONFIG_SCSI_AHCI_PLAT
+#define CONFIG_CMD_SCSI
+#define CONFIG_DOS_PARTITION
+#define CONFIG_BOARD_LATE_INIT
+
+#define CONFIG_SYS_SATA				AHCI_BASE_ADDR
+
+#define CONFIG_SYS_SCSI_MAX_SCSI_ID		1
+#define CONFIG_SYS_SCSI_MAX_LUN			1
+#define CONFIG_SYS_SCSI_MAX_DEVICE		(CONFIG_SYS_SCSI_MAX_SCSI_ID * \
+						CONFIG_SYS_SCSI_MAX_LUN)
+#define CONFIG_PCI		/* Enable PCI/PCIE */
+#define CONFIG_PCIE1		/* PCIE controller 1 */
+#define CONFIG_PCIE_LAYERSCAPE	/* Use common FSL Layerscape PCIe code */
+#define FSL_PCIE_COMPAT "fsl,ls1043a-pcie"
+
+#define CONFIG_SYS_PCI_64BIT
+
+#define CONFIG_SYS_PCIE_CFG0_PHYS_OFF	0x00000000
+#define CONFIG_SYS_PCIE_CFG0_SIZE	0x00001000	/* 4k */
+#define CONFIG_SYS_PCIE_CFG1_PHYS_OFF	0x00001000
+#define CONFIG_SYS_PCIE_CFG1_SIZE	0x00001000	/* 4k */
+
+#define CONFIG_SYS_PCIE_IO_BUS		0x00000000
+#define CONFIG_SYS_PCIE_IO_PHYS_OFF	0x00010000
+#define CONFIG_SYS_PCIE_IO_SIZE		0x00010000	/* 64k */
+
+#define CONFIG_SYS_PCIE_MEM_BUS         0x08000000
+#define CONFIG_SYS_PCIE_MEM_PHYS_OFF    0x04000000
+#define CONFIG_SYS_PCIE_MEM_SIZE        0x80000000      /* 128M */
+
+#define CONFIG_NET_MULTI
+#define CONFIG_PCI_PNP
+#define CONFIG_PCI_SCAN_SHOW
+#define CONFIG_CMD_PCI
+
+#define CONFIG_CMD_MEMINFO
+#define CONFIG_CMD_MEMTEST
+#define CONFIG_SYS_MEMTEST_START	0x80000000
+#define CONFIG_SYS_MEMTEST_END		0x9fffffff
+
+#define CONFIG_MISC_INIT_R
+
+#endif /* __LS1012AQDS_H__ */
diff --git a/include/configs/ls1012ardb.h b/include/configs/ls1012ardb.h
new file mode 100644
index 0000000..6046ab7
--- /dev/null
+++ b/include/configs/ls1012ardb.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __LS1012ARDB_H__
+#define __LS1012ARDB_H__
+
+#include "ls1012a_common.h"
+
+
+#define CONFIG_DIMM_SLOTS_PER_CTLR	1
+#define CONFIG_CHIP_SELECTS_PER_CTRL	1
+#define CONFIG_NR_DRAM_BANKS		2
+#define CONFIG_SYS_SDRAM_SIZE		0x40000000
+
+#define CONFIG_SYS_MMDC_CORE_CONTROL_1		0x05180000
+#define CONFIG_SYS_MMDC_CORE_CONTROL_2		0x85180000
+
+#define CONFIG_CMD_MEMINFO
+#define CONFIG_CMD_MEMTEST
+#define CONFIG_SYS_MEMTEST_START	0x80000000
+#define CONFIG_SYS_MEMTEST_END		0x9fffffff
+
+/*
+* USB
+*/
+#define CONFIG_HAS_FSL_XHCI_USB
+
+#ifdef CONFIG_HAS_FSL_XHCI_USB
+#define CONFIG_USB_XHCI_FSL
+#define CONFIG_USB_MAX_CONTROLLER_COUNT         1
+#define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS      2
+#define CONFIG_USB_STORAGE
+#endif
+
+/*
+ * I2C IO expander
+ */
+
+#define I2C_MUX_IO1_ADDR	0x24
+#define __SW_BOOT_MASK		0xFC
+#define __SW_BOOT_EMU		0x10
+#define __SW_BOOT_BANK1		0x00
+#define __SW_BOOT_BANK2		0x01
+#define __SW_REV_MASK		0x07
+#define __SW_REV_A		0xF8
+#define __SW_REV_B		0xF0
+
+/*  MMC  */
+#define CONFIG_MMC
+#ifdef CONFIG_MMC
+#define CONFIG_FSL_ESDHC
+#define CONFIG_SYS_FSL_MMC_HAS_CAPBLT_VS33
+#define CONFIG_GENERIC_MMC
+#define CONFIG_DOS_PARTITION
+#endif
+
+/* SATA */
+#define CONFIG_LIBATA
+#define	CONFIG_SCSI
+#define CONFIG_SCSI_AHCI
+#define CONFIG_SCSI_AHCI_PLAT
+#define CONFIG_CMD_SCSI
+#define CONFIG_DOS_PARTITION
+#define CONFIG_BOARD_LATE_INIT
+
+#define CONFIG_SYS_SATA				AHCI_BASE_ADDR
+
+#define CONFIG_SYS_SCSI_MAX_SCSI_ID		1
+#define CONFIG_SYS_SCSI_MAX_LUN			1
+#define CONFIG_SYS_SCSI_MAX_DEVICE		(CONFIG_SYS_SCSI_MAX_SCSI_ID * \
+						CONFIG_SYS_SCSI_MAX_LUN)
+#define CONFIG_PCI		/* Enable PCI/PCIE */
+#define CONFIG_PCIE1		/* PCIE controller 1 */
+#define CONFIG_PCIE_LAYERSCAPE	/* Use common FSL Layerscape PCIe code */
+#define FSL_PCIE_COMPAT "fsl,ls1043a-pcie"
+
+#define CONFIG_SYS_PCI_64BIT
+
+#define CONFIG_SYS_PCIE_CFG0_PHYS_OFF	0x00000000
+#define CONFIG_SYS_PCIE_CFG0_SIZE	0x00001000	/* 4k */
+#define CONFIG_SYS_PCIE_CFG1_PHYS_OFF	0x00001000
+#define CONFIG_SYS_PCIE_CFG1_SIZE	0x00001000	/* 4k */
+
+#define CONFIG_SYS_PCIE_IO_BUS		0x00000000
+#define CONFIG_SYS_PCIE_IO_PHYS_OFF	0x00010000
+#define CONFIG_SYS_PCIE_IO_SIZE		0x00010000	/* 64k */
+
+#define CONFIG_SYS_PCIE_MEM_BUS         0x08000000
+#define CONFIG_SYS_PCIE_MEM_PHYS_OFF    0x04000000
+#define CONFIG_SYS_PCIE_MEM_SIZE        0x80000000      /* 128M */
+
+#define CONFIG_NET_MULTI
+#define CONFIG_PCI_PNP
+#define CONFIG_PCI_SCAN_SHOW
+#define CONFIG_CMD_PCI
+
+#define CONFIG_CMD_MEMINFO
+#define CONFIG_CMD_MEMTEST
+#define CONFIG_SYS_MEMTEST_START	0x80000000
+#define CONFIG_SYS_MEMTEST_END		0x9fffffff
+
+#endif /* __LS1012ARDB_H__ */
diff --git a/include/configs/p2771-0000.h b/include/configs/p2771-0000.h
new file mode 100644
index 0000000..257283f
--- /dev/null
+++ b/include/configs/p2771-0000.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2013-2016, NVIDIA CORPORATION.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef _P2771_0000_H
+#define _P2771_0000_H
+
+#include <linux/sizes.h>
+
+#include "tegra186-common.h"
+
+/* High-level configuration options */
+#define CONFIG_TEGRA_BOARD_STRING	"NVIDIA P2771-0000"
+
+/* SD/MMC */
+#define CONFIG_MMC
+#define CONFIG_GENERIC_MMC
+#define CONFIG_TEGRA_MMC
+
+/* Environment in eMMC, at the end of 2nd "boot sector" */
+#define CONFIG_ENV_IS_IN_MMC
+#define CONFIG_SYS_MMC_ENV_DEV		0
+#define CONFIG_SYS_MMC_ENV_PART		2
+#define CONFIG_ENV_OFFSET		(-CONFIG_ENV_SIZE)
+
+#include "tegra-common-post.h"
+
+/* Crystal is 38.4MHz. clk_m runs at half that rate */
+#define COUNTER_FREQUENCY	19200000
+
+#endif
diff --git a/include/configs/tegra-common.h b/include/configs/tegra-common.h
index 92d4dd8..7b0940a 100644
--- a/include/configs/tegra-common.h
+++ b/include/configs/tegra-common.h
@@ -111,7 +111,6 @@
 						CONFIG_SYS_INIT_RAM_SIZE - \
 						GENERATED_GBL_DATA_SIZE)
 
-#define CONFIG_TEGRA_GPIO
 #define CONFIG_CMD_ENTERRCM
 
 /* Defines for SPL */
diff --git a/include/configs/tegra186-common.h b/include/configs/tegra186-common.h
new file mode 100644
index 0000000..aa7b9d0
--- /dev/null
+++ b/include/configs/tegra186-common.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2013-2016, NVIDIA CORPORATION.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef _TEGRA186_COMMON_H_
+#define _TEGRA186_COMMON_H_
+
+#include "tegra-common.h"
+
+/* Cortex-A57 uses a cache line size of 64 bytes */
+#define CONFIG_SYS_CACHELINE_SIZE	64
+
+/*
+ * NS16550 Configuration
+ */
+#define V_NS16550_CLK		408000000	/* 408MHz (pllp_out0) */
+
+/*
+ * Miscellaneous configurable options
+ */
+#define CONFIG_STACKBASE	0x82800000	/* 40MB */
+
+/*-----------------------------------------------------------------------
+ * Physical Memory Map
+ */
+
+#define CONFIG_SYS_TEXT_BASE	0x80080000
+
+/* Generic Interrupt Controller */
+#define CONFIG_GICV2
+
+/*
+ * Memory layout for where various images get loaded by boot scripts:
+ *
+ * scriptaddr can be pretty much anywhere that doesn't conflict with something
+ *   else. Put it above BOOTMAPSZ to eliminate conflicts.
+ *
+ * pxefile_addr_r can be pretty much anywhere that doesn't conflict with
+ *   something else. Put it above BOOTMAPSZ to eliminate conflicts.
+ *
+ * kernel_addr_r must be within the first 128M of RAM in order for the
+ *   kernel's CONFIG_AUTO_ZRELADDR option to work. Since the kernel will
+ *   decompress itself to 0x8000 after the start of RAM, kernel_addr_r
+ *   should not overlap that area, or the kernel will have to copy itself
+ *   somewhere else before decompression. Similarly, the address of any other
+ *   data passed to the kernel shouldn't overlap the start of RAM. Pushing
+ *   this up to 16M allows for a sizable kernel to be decompressed below the
+ *   compressed load address.
+ *
+ * fdt_addr_r simply shouldn't overlap anything else. Choosing 32M allows for
+ *   the compressed kernel to be up to 16M too.
+ *
+ * ramdisk_addr_r simply shouldn't overlap anything else. Choosing 33M allows
+ *   for the FDT/DTB to be up to 1M, which is hopefully plenty.
+ */
+#define CONFIG_LOADADDR 0x80080000
+#define MEM_LAYOUT_ENV_SETTINGS \
+	"scriptaddr=0x90000000\0" \
+	"pxefile_addr_r=0x90100000\0" \
+	"kernel_addr_r=" __stringify(CONFIG_LOADADDR) "\0" \
+	"fdt_addr_r=0x82000000\0" \
+	"ramdisk_addr_r=0x82100000\0"
+
+/* Defines for SPL */
+#define CONFIG_SPL_TEXT_BASE		0x80108000
+#define CONFIG_SYS_SPL_MALLOC_START	0x80090000
+#define CONFIG_SPL_STACK		0x800ffffc
+
+#endif
diff --git a/include/configs/xilinx_zynqmp.h b/include/configs/xilinx_zynqmp.h
index 8a1142b..b848150 100644
--- a/include/configs/xilinx_zynqmp.h
+++ b/include/configs/xilinx_zynqmp.h
@@ -76,7 +76,6 @@
 #define CONFIG_BOOTP_GATEWAY
 #define CONFIG_BOOTP_HOSTNAME
 #define CONFIG_BOOTP_MAY_FAIL
-#define CONFIG_BOOTP_SERVERIP
 #define CONFIG_BOOTP_DNS
 #define CONFIG_BOOTP_PXE
 #define CONFIG_BOOTP_SUBNETMASK
@@ -105,7 +104,6 @@
 #endif
 
 #ifdef CONFIG_NAND_ARASAN
-# define CONFIG_CMD_NAND
 # define CONFIG_CMD_NAND_LOCK_UNLOCK
 # define CONFIG_SYS_MAX_NAND_DEVICE	1
 # define CONFIG_SYS_NAND_SELF_INIT
@@ -146,21 +144,6 @@
 # define DFU_ALT_INFO
 #endif
 
-/* Initial environment variables */
-#ifndef CONFIG_EXTRA_ENV_SETTINGS
-#define CONFIG_EXTRA_ENV_SETTINGS \
-	"kernel_addr=0x80000\0" \
-	"fdt_addr=0x7000000\0" \
-	"fdt_high=0x10000000\0" \
-	CONFIG_KERNEL_FDT_OFST_SIZE \
-	"sdbootdev=0\0"\
-	"sdboot=mmc dev $sdbootdev && mmcinfo && load mmc $sdbootdev:$partid $fdt_addr system.dtb && " \
-		"load mmc $sdbootdev:$partid $kernel_addr Image && " \
-		"booti $kernel_addr - $fdt_addr\0" \
-	DFU_ALT_INFO
-#endif
-
-#define CONFIG_BOOTCOMMAND	"run $modeboot"
 #define CONFIG_BOOTDELAY	3
 
 #define CONFIG_BOARD_LATE_INIT
@@ -188,6 +171,8 @@
 # define CONFIG_PHY_NATSEMI
 # define CONFIG_PHY_TI
 # define CONFIG_PHY_GIGE
+# define CONFIG_PHY_VITESSE
+# define CONFIG_PHY_REALTEK
 # define PHY_ANEG_TIMEOUT       20000
 #endif
 
@@ -208,7 +193,8 @@
 # define CONFIG_SYS_EEPROM_SIZE			(64 * 1024)
 #endif
 
-#ifdef CONFIG_AHCI
+#ifdef CONFIG_SATA_CEVA
+#define CONFIG_AHCI
 #define CONFIG_LIBATA
 #define CONFIG_SCSI_AHCI
 #define CONFIG_SCSI_AHCI_PLAT
@@ -227,6 +213,50 @@
 #define CONFIG_BOARD_EARLY_INIT_R
 #define CONFIG_CLOCKS
 
+#define ENV_MEM_LAYOUT_SETTINGS \
+	"fdt_high=10000000\0" \
+	"initrd_high=10000000\0" \
+	"fdt_addr_r=0x40000000\0" \
+	"pxefile_addr_r=0x10000000\0" \
+	"kernel_addr_r=0x18000000\0" \
+	"scriptaddr=0x02000000\0" \
+	"ramdisk_addr_r=0x02100000\0" \
+
+#if defined(CONFIG_ZYNQ_SDHCI)
+# define BOOT_TARGET_DEVICES_MMC(func)	func(MMC, mmc, 0) func(MMC, mmc, 1)
+#else
+# define BOOT_TARGET_DEVICES_MMC(func)
+#endif
+
+#if defined(CONFIG_SATA_CEVA)
+# define BOOT_TARGET_DEVICES_SCSI(func)	func(SCSI, scsi, 0)
+#else
+# define BOOT_TARGET_DEVICES_SCSI(func)
+#endif
+
+#if defined(CONFIG_ZYNQMP_USB)
+# define BOOT_TARGET_DEVICES_USB(func)	func(USB, usb, 0) func(USB, usb, 1)
+#else
+# define BOOT_TARGET_DEVICES_USB(func)
+#endif
+
+#define BOOT_TARGET_DEVICES(func) \
+	BOOT_TARGET_DEVICES_MMC(func) \
+	BOOT_TARGET_DEVICES_USB(func) \
+	BOOT_TARGET_DEVICES_SCSI(func) \
+	func(PXE, pxe, na) \
+	func(DHCP, dhcp, na)
+
+#include <config_distro_bootcmd.h>
+
+/* Initial environment variables */
+#ifndef CONFIG_EXTRA_ENV_SETTINGS
+#define CONFIG_EXTRA_ENV_SETTINGS \
+	ENV_MEM_LAYOUT_SETTINGS \
+	BOOTENV \
+	DFU_ALT_INFO
+#endif
+
 #define CONFIG_SPL_TEXT_BASE		0xfffc0000
 #define CONFIG_SPL_MAX_SIZE		0x20000
 
diff --git a/include/configs/xilinx_zynqmp_ep.h b/include/configs/xilinx_zynqmp_ep.h
index 9506355..c5bd5da 100644
--- a/include/configs/xilinx_zynqmp_ep.h
+++ b/include/configs/xilinx_zynqmp_ep.h
@@ -22,13 +22,6 @@
 
 #define COUNTER_FREQUENCY	4000000
 
-#define CONFIG_KERNEL_FDT_OFST_SIZE \
-	"kernel_offset=0x400000\0" \
-	"fdt_offset=0x2400000\0" \
-	"kernel_size=0x2000000\0" \
-	"fdt_size=0x80000\0" \
-	"board=ep108\0"
-
 #include <configs/xilinx_zynqmp.h>
 
 #endif /* __CONFIG_ZYNQMP_EP_H */
diff --git a/include/configs/xilinx_zynqmp_zc1751_xm015_dc1.h b/include/configs/xilinx_zynqmp_zc1751_xm015_dc1.h
index 3c0ba88..c9f4432 100644
--- a/include/configs/xilinx_zynqmp_zc1751_xm015_dc1.h
+++ b/include/configs/xilinx_zynqmp_zc1751_xm015_dc1.h
@@ -17,13 +17,6 @@
 
 #define CONFIG_IDENT_STRING	" Xilinx ZynqMP ZC1751 xm015 dc1"
 
-#define CONFIG_KERNEL_FDT_OFST_SIZE \
-	"kernel_offset=0x400000\0" \
-	"fdt_offset=0x2400000\0" \
-	"kernel_size=0x2000000\0" \
-	"fdt_size=0x80000\0" \
-	"board=zc1751-dc1\0"
-
 #include <configs/xilinx_zynqmp.h>
 
 #endif /* __CONFIG_ZYNQMP_ZC1751_XM015_DC1_H */
diff --git a/include/configs/xilinx_zynqmp_zc1751_xm016_dc2.h b/include/configs/xilinx_zynqmp_zc1751_xm016_dc2.h
index 83ea624..526d0bb 100644
--- a/include/configs/xilinx_zynqmp_zc1751_xm016_dc2.h
+++ b/include/configs/xilinx_zynqmp_zc1751_xm016_dc2.h
@@ -14,13 +14,6 @@
 
 #define CONFIG_IDENT_STRING	" Xilinx ZynqMP ZC1751 xm016 dc2"
 
-#define CONFIG_KERNEL_FDT_OFST_SIZE \
-	"kernel_offset=0x400000\0" \
-	"fdt_offset=0x2400000\0" \
-	"kernel_size=0x2000000\0" \
-	"fdt_size=0x80000\0" \
-	"board=zc1751-dc2\0"
-
 #include <configs/xilinx_zynqmp.h>
 
 #endif /* __CONFIG_ZYNQMP_ZC1751_XM016_DC2_H */
diff --git a/include/configs/xilinx_zynqmp_zc1751_xm018_dc4.h b/include/configs/xilinx_zynqmp_zc1751_xm018_dc4.h
new file mode 100644
index 0000000..65277a6
--- /dev/null
+++ b/include/configs/xilinx_zynqmp_zc1751_xm018_dc4.h
@@ -0,0 +1,17 @@
+/*
+ * Configuration for Xilinx ZynqMP zc1751 XM018 DC4
+ *
+ * (C) Copyright 2015 Xilinx, Inc.
+ * Michal Simek <michal.simek@xilinx.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __CONFIG_ZYNQMP_ZC1751_XM018_DC4_H
+#define __CONFIG_ZYNQMP_ZC1751_XM018_DC4_H
+
+#define CONFIG_IDENT_STRING	" Xilinx ZynqMP ZC1751 xm018 dc4"
+
+#include <configs/xilinx_zynqmp.h>
+
+#endif /* __CONFIG_ZYNQMP_ZC1751_XM018_DC4_H */
diff --git a/include/configs/xilinx_zynqmp_zc1751_xm019_dc5.h b/include/configs/xilinx_zynqmp_zc1751_xm019_dc5.h
index 4f8f5c1..76350d9 100644
--- a/include/configs/xilinx_zynqmp_zc1751_xm019_dc5.h
+++ b/include/configs/xilinx_zynqmp_zc1751_xm019_dc5.h
@@ -15,13 +15,6 @@
 
 #define CONFIG_IDENT_STRING	" Xilinx ZynqMP ZC1751 xm019 dc5"
 
-#define CONFIG_KERNEL_FDT_OFST_SIZE \
-	"kernel_offset=0x400000\0" \
-	"fdt_offset=0x2400000\0" \
-	"kernel_size=0x2000000\0" \
-	"fdt_size=0x80000\0" \
-	"board=zc1751-dc5\0"
-
 #include <configs/xilinx_zynqmp.h>
 
 #endif /* __CONFIG_ZYNQMP_ZC1751_XM019_DC5_H */
diff --git a/include/configs/xilinx_zynqmp_zcu102.h b/include/configs/xilinx_zynqmp_zcu102.h
index 81079fe..7ceab32 100644
--- a/include/configs/xilinx_zynqmp_zcu102.h
+++ b/include/configs/xilinx_zynqmp_zcu102.h
@@ -41,7 +41,6 @@
 #define CONFIG_CMD_PCA953X
 #define CONFIG_CMD_PCA953X_INFO
 
-#define CONFIG_AHCI
 #define CONFIG_SATA_CEVA
 
 #define CONFIG_ZYNQMP_XHCI_LIST {ZYNQMP_USB0_XHCI_BASEADDR}
@@ -54,13 +53,6 @@
 #define CONFIG_ZYNQ_GEM_EEPROM_ADDR	0x54
 #define CONFIG_ZYNQ_GEM_I2C_MAC_OFFSET	0x20
 
-#define CONFIG_KERNEL_FDT_OFST_SIZE \
-	"kernel_offset=0x180000\0" \
-	"fdt_offset=0x100000\0" \
-	"kernel_size=0x1e00000\0" \
-	"fdt_size=0x80000\0" \
-	"board=zcu102\0"
-
 #include <configs/xilinx_zynqmp.h>
 
 #endif /* __CONFIG_ZYNQMP_ZCU102_H */
diff --git a/include/dt-bindings/gpio/tegra-gpio.h b/include/dt-bindings/gpio/tegra-gpio.h
index 197dc28..a1c09e8 100644
--- a/include/dt-bindings/gpio/tegra-gpio.h
+++ b/include/dt-bindings/gpio/tegra-gpio.h
@@ -12,40 +12,40 @@
 
 #include <dt-bindings/gpio/gpio.h>
 
-#define TEGRA_GPIO_BANK_ID_A 0
-#define TEGRA_GPIO_BANK_ID_B 1
-#define TEGRA_GPIO_BANK_ID_C 2
-#define TEGRA_GPIO_BANK_ID_D 3
-#define TEGRA_GPIO_BANK_ID_E 4
-#define TEGRA_GPIO_BANK_ID_F 5
-#define TEGRA_GPIO_BANK_ID_G 6
-#define TEGRA_GPIO_BANK_ID_H 7
-#define TEGRA_GPIO_BANK_ID_I 8
-#define TEGRA_GPIO_BANK_ID_J 9
-#define TEGRA_GPIO_BANK_ID_K 10
-#define TEGRA_GPIO_BANK_ID_L 11
-#define TEGRA_GPIO_BANK_ID_M 12
-#define TEGRA_GPIO_BANK_ID_N 13
-#define TEGRA_GPIO_BANK_ID_O 14
-#define TEGRA_GPIO_BANK_ID_P 15
-#define TEGRA_GPIO_BANK_ID_Q 16
-#define TEGRA_GPIO_BANK_ID_R 17
-#define TEGRA_GPIO_BANK_ID_S 18
-#define TEGRA_GPIO_BANK_ID_T 19
-#define TEGRA_GPIO_BANK_ID_U 20
-#define TEGRA_GPIO_BANK_ID_V 21
-#define TEGRA_GPIO_BANK_ID_W 22
-#define TEGRA_GPIO_BANK_ID_X 23
-#define TEGRA_GPIO_BANK_ID_Y 24
-#define TEGRA_GPIO_BANK_ID_Z 25
-#define TEGRA_GPIO_BANK_ID_AA 26
-#define TEGRA_GPIO_BANK_ID_BB 27
-#define TEGRA_GPIO_BANK_ID_CC 28
-#define TEGRA_GPIO_BANK_ID_DD 29
-#define TEGRA_GPIO_BANK_ID_EE 30
-#define TEGRA_GPIO_BANK_ID_FF 31
+#define TEGRA_GPIO_PORT_A 0
+#define TEGRA_GPIO_PORT_B 1
+#define TEGRA_GPIO_PORT_C 2
+#define TEGRA_GPIO_PORT_D 3
+#define TEGRA_GPIO_PORT_E 4
+#define TEGRA_GPIO_PORT_F 5
+#define TEGRA_GPIO_PORT_G 6
+#define TEGRA_GPIO_PORT_H 7
+#define TEGRA_GPIO_PORT_I 8
+#define TEGRA_GPIO_PORT_J 9
+#define TEGRA_GPIO_PORT_K 10
+#define TEGRA_GPIO_PORT_L 11
+#define TEGRA_GPIO_PORT_M 12
+#define TEGRA_GPIO_PORT_N 13
+#define TEGRA_GPIO_PORT_O 14
+#define TEGRA_GPIO_PORT_P 15
+#define TEGRA_GPIO_PORT_Q 16
+#define TEGRA_GPIO_PORT_R 17
+#define TEGRA_GPIO_PORT_S 18
+#define TEGRA_GPIO_PORT_T 19
+#define TEGRA_GPIO_PORT_U 20
+#define TEGRA_GPIO_PORT_V 21
+#define TEGRA_GPIO_PORT_W 22
+#define TEGRA_GPIO_PORT_X 23
+#define TEGRA_GPIO_PORT_Y 24
+#define TEGRA_GPIO_PORT_Z 25
+#define TEGRA_GPIO_PORT_AA 26
+#define TEGRA_GPIO_PORT_BB 27
+#define TEGRA_GPIO_PORT_CC 28
+#define TEGRA_GPIO_PORT_DD 29
+#define TEGRA_GPIO_PORT_EE 30
+#define TEGRA_GPIO_PORT_FF 31
 
-#define TEGRA_GPIO(bank, offset) \
-	((TEGRA_GPIO_BANK_ID_##bank * 8) + offset)
+#define TEGRA_GPIO(port, offset) \
+	((TEGRA_GPIO_PORT_##port * 8) + offset)
 
 #endif
diff --git a/include/dt-bindings/gpio/tegra186-gpio.h b/include/dt-bindings/gpio/tegra186-gpio.h
new file mode 100644
index 0000000..7e6fb95
--- /dev/null
+++ b/include/dt-bindings/gpio/tegra186-gpio.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2016, NVIDIA CORPORATION.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ *
+ * This header provides constants for binding nvidia,tegra186-gpio*.
+ *
+ * The first cell in Tegra's GPIO specifier is the GPIO ID. The macros below
+ * provide names for this.
+ *
+ * The second cell contains standard flag values specified in gpio.h.
+ */
+
+#ifndef _DT_BINDINGS_GPIO_TEGRA186_GPIO_H
+#define _DT_BINDINGS_GPIO_TEGRA186_GPIO_H
+
+#include <dt-bindings/gpio/gpio.h>
+
+/* GPIOs implemented by main GPIO controller */
+#define TEGRA_MAIN_GPIO_PORT_A 0
+#define TEGRA_MAIN_GPIO_PORT_B 1
+#define TEGRA_MAIN_GPIO_PORT_C 2
+#define TEGRA_MAIN_GPIO_PORT_D 3
+#define TEGRA_MAIN_GPIO_PORT_E 4
+#define TEGRA_MAIN_GPIO_PORT_F 5
+#define TEGRA_MAIN_GPIO_PORT_G 6
+#define TEGRA_MAIN_GPIO_PORT_H 7
+#define TEGRA_MAIN_GPIO_PORT_I 8
+#define TEGRA_MAIN_GPIO_PORT_J 9
+#define TEGRA_MAIN_GPIO_PORT_K 10
+#define TEGRA_MAIN_GPIO_PORT_L 11
+#define TEGRA_MAIN_GPIO_PORT_M 12
+#define TEGRA_MAIN_GPIO_PORT_N 13
+#define TEGRA_MAIN_GPIO_PORT_O 14
+#define TEGRA_MAIN_GPIO_PORT_P 15
+#define TEGRA_MAIN_GPIO_PORT_Q 16
+#define TEGRA_MAIN_GPIO_PORT_R 17
+#define TEGRA_MAIN_GPIO_PORT_T 18
+#define TEGRA_MAIN_GPIO_PORT_X 19
+#define TEGRA_MAIN_GPIO_PORT_Y 20
+#define TEGRA_MAIN_GPIO_PORT_BB 21
+#define TEGRA_MAIN_GPIO_PORT_CC 22
+
+#define TEGRA_MAIN_GPIO(port, offset) \
+	((TEGRA_MAIN_GPIO_PORT_##port * 8) + offset)
+
+/* GPIOs implemented by AON GPIO controller */
+#define TEGRA_AON_GPIO_PORT_S 0
+#define TEGRA_AON_GPIO_PORT_U 1
+#define TEGRA_AON_GPIO_PORT_V 2
+#define TEGRA_AON_GPIO_PORT_W 3
+#define TEGRA_AON_GPIO_PORT_Z 4
+#define TEGRA_AON_GPIO_PORT_AA 5
+#define TEGRA_AON_GPIO_PORT_EE 6
+#define TEGRA_AON_GPIO_PORT_FF 7
+
+#define TEGRA_AON_GPIO(port, offset) \
+	((TEGRA_AON_GPIO_PORT_##port * 8) + offset)
+
+#endif
diff --git a/include/fdtdec.h b/include/fdtdec.h
index 37d482a..54e3d81 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -123,6 +123,7 @@
 	COMPAT_NVIDIA_TEGRA124_SOR,	/* Tegra 124 Serial Output Resource */
 	COMPAT_NVIDIA_TEGRA124_PMC,	/* Tegra 124 power mgmt controller */
 	COMPAT_NVIDIA_TEGRA20_DC,	/* Tegra 2 Display controller */
+	COMPAT_NVIDIA_TEGRA186_SDMMC,	/* Tegra186 SDMMC controller */
 	COMPAT_NVIDIA_TEGRA210_SDMMC,	/* Tegra210 SDMMC controller */
 	COMPAT_NVIDIA_TEGRA124_SDMMC,	/* Tegra124 SDMMC controller */
 	COMPAT_NVIDIA_TEGRA30_SDMMC,	/* Tegra30 SDMMC controller */
diff --git a/include/fsl_mmdc.h b/include/fsl_mmdc.h
new file mode 100644
index 0000000..281a819
--- /dev/null
+++ b/include/fsl_mmdc.h
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef FSL_MMDC_H
+#define FSL_MMDC_H
+
+#define CONFIG_SYS_MMDC_CORE_ODT_TIMING		0x12554000
+#define CONFIG_SYS_MMDC_CORE_TIMING_CFG_0	0xbabf7954
+#define CONFIG_SYS_MMDC_CORE_TIMING_CFG_1	0xff328f64
+#define CONFIG_SYS_MMDC_CORE_TIMING_CFG_2	0x01ff00db
+
+#define CONFIG_SYS_MMDC_CORE_MISC		0x00000680
+#define CONFIG_SYS_MMDC_PHY_MEASURE_UNIT	0x00000800
+#define CONFIG_SYS_MMDC_CORE_RDWR_CMD_DELAY	0x00002000
+#define CONFIG_SYS_MMDC_PHY_ODT_CTRL		0x0000022a
+
+#define CONFIG_SYS_MMDC_CORE_OUT_OF_RESET_DELAY	0x00bf1023
+
+#define CONFIG_SYS_MMDC_CORE_ADDR_PARTITION	0x0000007f
+
+#define CONFIG_SYS_MMDC_PHY_ZQ_HW_CTRL		0xa1390003
+
+#define	FORCE_ZQ_AUTO_CALIBRATION		(0x1 << 16)
+
+/* PHY Write Leveling Configuration and Error Status (MPWLGCR) */
+#define WR_LVL_HW_EN				0x00000001
+
+/* PHY Pre-defined Compare and CA delay-line Configuration (MPPDCMPR2) */
+#define MPR_COMPARE_EN				0x00000001
+
+#define CONFIG_SYS_MMDC_PHY_RD_DLY_LINES_CFG	0x40404040
+
+/* MMDC PHY Read DQS gating control register 0 (MPDGCTRL0) */
+#define AUTO_RD_DQS_GATING_CALIBRATION_EN	0x10000000
+
+/* MMDC PHY Read Delay HW Calibration Control Register (MPRDDLHWCTL) */
+#define AUTO_RD_CALIBRATION_EN			0x00000010
+
+#define CONFIG_SYS_MMDC_CORE_PWR_DOWN_CTRL	0x00030035
+
+#define CONFIG_SYS_MMDC_CORE_PWR_SAV_CTRL_STAT	0x00001067
+
+#define CONFIG_SYS_MMDC_CORE_REFRESH_CTL	0x103e8000
+
+#define START_REFRESH				0x00000001
+
+/* MMDC Core Special Command Register (MDSCR) */
+#define CMD_ADDR_MSB_MR_OP(x)   (x << 24)
+
+#define  CMD_ADDR_LSB_MR_ADDR(x)    (x << 16)
+
+#define DISABLE_CFG_REQ		0x0
+#define CONFIGURATION_REQ	(0x1  << 15)
+#define WL_EN			(0x1  << 9)
+
+#define	CMD_NORMAL		(0x0 << 4)
+#define	CMD_PRECHARGE		(0x1 << 4)
+#define	CMD_AUTO_REFRESH	(0x2 << 4)
+#define	CMD_LOAD_MODE_REG	(0x3 << 4)
+#define	CMD_ZQ_CALIBRATION	(0x4 << 4)
+#define	CMD_PRECHARGE_BANK_OPEN	(0x5 << 4)
+#define	CMD_MRR			(0x6 << 4)
+
+#define CMD_BANK_ADDR_0		0x0
+#define CMD_BANK_ADDR_1		0x1
+#define CMD_BANK_ADDR_2		0x2
+#define CMD_BANK_ADDR_3		0x3
+#define CMD_BANK_ADDR_4		0x4
+#define CMD_BANK_ADDR_5		0x5
+#define CMD_BANK_ADDR_6		0x6
+#define CMD_BANK_ADDR_7		0x7
+
+/* MMDC Registers */
+struct mmdc_p_regs {
+	u32 mdctl;
+	u32 mdpdc;
+	u32 mdotc;
+	u32 mdcfg0;
+	u32 mdcfg1;
+	u32 mdcfg2;
+	u32 mdmisc;
+	u32 mdscr;
+	u32 mdref;
+	u32 res1[2];
+	u32 mdrwd;
+	u32 mdor;
+	u32 mdmrr;
+	u32 mdcfg3lp;
+	u32 mdmr4;
+	u32 mdasp;
+	u32 res2[239];
+	u32 maarcr;
+	u32 mapsr;
+	u32 maexidr0;
+	u32 maexidr1;
+	u32 madpcr0;
+	u32 madpcr1;
+	u32 madpsr0;
+	u32 madpsr1;
+	u32 madpsr2;
+	u32 madpsr3;
+	u32 madpsr4;
+	u32 madpsr5;
+	u32 masbs0;
+	u32 masbs1;
+	u32 res3[2];
+	u32 magenp;
+	u32 res4[239];
+	u32 mpzqhwctrl;
+	u32 mpzqswctrl;
+	u32 mpwlgcr;
+	u32 mpwldectrl0;
+	u32 mpwldectrl1;
+	u32 mpwldlst;
+	u32 mpodtctrl;
+	u32 mprddqby0dl;
+	u32 mprddqby1dl;
+	u32 mprddqby2dl;
+	u32 mprddqby3dl;
+	u32 res5[4];
+	u32 mpdgctrl0;
+	u32 mpdgctrl1;
+	u32 mpdgdlst0;
+	u32 mprddlctl;
+	u32 mprddlst;
+	u32 mpwrdlctl;
+	u32 mpwrdlst;
+	u32 mpsdctrl;
+	u32 mpzqlp2ctl;
+	u32 mprddlhwctl;
+	u32 mpwrdlhwctl;
+	u32 mprddlhwst0;
+	u32 mprddlhwst1;
+	u32 mpwrdlhwst0;
+	u32 mpwrdlhwst1;
+	u32 mpwlhwerr;
+	u32 mpdghwst0;
+	u32 mpdghwst1;
+	u32 mpdghwst2;
+	u32 mpdghwst3;
+	u32 mppdcmpr1;
+	u32 mppdcmpr2;
+	u32 mpswdar0;
+	u32 mpswdrdr0;
+	u32 mpswdrdr1;
+	u32 mpswdrdr2;
+	u32 mpswdrdr3;
+	u32 mpswdrdr4;
+	u32 mpswdrdr5;
+	u32 mpswdrdr6;
+	u32 mpswdrdr7;
+	u32 mpmur0;
+	u32 mpwrcadl;
+	u32 mpdccr;
+};
+
+#endif /* FSL_MMDC_H */
diff --git a/include/linux/mtd/docg4.h b/include/linux/mtd/docg4.h
deleted file mode 100644
index 741fc0d..0000000
--- a/include/linux/mtd/docg4.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (C) 2013 Mike Dunn <mikedunn@newsguy.com>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#ifndef __DOCG4_H__
-#define __DOCG4_H__
-
-#include <common.h>
-#include <linux/mtd/nand.h>
-
-extern int docg4_nand_init(struct mtd_info *mtd,
-			   struct nand_chip *nand, int devnum);
-
-/* SPL-related definitions */
-#define DOCG4_IPL_LOAD_BLOCK_COUNT 2  /* number of blocks that IPL loads */
-#define DOCG4_BLOCK_CAPACITY_SPL 0x10000 /* reliable mode; redundant pages */
-
-#define DOC_IOSPACE_DATA		0x0800
-
-/* register offsets */
-#define DOC_CHIPID			0x1000
-#define DOC_DEVICESELECT		0x100a
-#define DOC_ASICMODE			0x100c
-#define DOC_DATAEND			0x101e
-#define DOC_NOP				0x103e
-
-#define DOC_FLASHSEQUENCE		0x1032
-#define DOC_FLASHCOMMAND		0x1034
-#define DOC_FLASHADDRESS		0x1036
-#define DOC_FLASHCONTROL		0x1038
-#define DOC_ECCCONF0			0x1040
-#define DOC_ECCCONF1			0x1042
-#define DOC_HAMMINGPARITY		0x1046
-#define DOC_BCH_SYNDROM(idx)		(0x1048 + idx)
-
-#define DOC_ASICMODECONFIRM		0x1072
-#define DOC_CHIPID_INV			0x1074
-#define DOC_POWERMODE			0x107c
-
-#define DOCG4_MYSTERY_REG		0x1050
-
-/* apparently used only to write oob bytes 6 and 7 */
-#define DOCG4_OOB_6_7			0x1052
-
-/* DOC_FLASHSEQUENCE register commands */
-#define DOC_SEQ_RESET			0x00
-#define DOCG4_SEQ_PAGE_READ		0x03
-#define DOCG4_SEQ_FLUSH			0x29
-#define DOCG4_SEQ_PAGEWRITE		0x16
-#define DOCG4_SEQ_PAGEPROG		0x1e
-#define DOCG4_SEQ_BLOCKERASE		0x24
-
-/* DOC_FLASHCOMMAND register commands */
-#define DOCG4_CMD_PAGE_READ             0x00
-#define DOC_CMD_ERASECYCLE2		0xd0
-#define DOCG4_CMD_FLUSH                 0x70
-#define DOCG4_CMD_READ2                 0x30
-#define DOC_CMD_PROG_BLOCK_ADDR		0x60
-#define DOCG4_CMD_PAGEWRITE		0x80
-#define DOC_CMD_PROG_CYCLE2		0x10
-#define DOC_CMD_RESET			0xff
-
-/* DOC_POWERMODE register bits */
-#define DOC_POWERDOWN_READY		0x80
-
-/* DOC_FLASHCONTROL register bits */
-#define DOC_CTRL_CE			0x10
-#define DOC_CTRL_UNKNOWN		0x40
-#define DOC_CTRL_FLASHREADY		0x01
-
-/* DOC_ECCCONF0 register bits */
-#define DOC_ECCCONF0_READ_MODE		0x8000
-#define DOC_ECCCONF0_UNKNOWN		0x2000
-#define DOC_ECCCONF0_ECC_ENABLE	        0x1000
-#define DOC_ECCCONF0_DATA_BYTES_MASK	0x07ff
-
-/* DOC_ECCCONF1 register bits */
-#define DOC_ECCCONF1_BCH_SYNDROM_ERR	0x80
-#define DOC_ECCCONF1_ECC_ENABLE         0x07
-#define DOC_ECCCONF1_PAGE_IS_WRITTEN	0x20
-
-/* DOC_ASICMODE register bits */
-#define DOC_ASICMODE_RESET		0x00
-#define DOC_ASICMODE_NORMAL		0x01
-#define DOC_ASICMODE_POWERDOWN		0x02
-#define DOC_ASICMODE_MDWREN		0x04
-#define DOC_ASICMODE_BDETCT_RESET	0x08
-#define DOC_ASICMODE_RSTIN_RESET	0x10
-#define DOC_ASICMODE_RAM_WE		0x20
-
-/* good status values read after read/write/erase operations */
-#define DOCG4_PROGSTATUS_GOOD          0x51
-#define DOCG4_PROGSTATUS_GOOD_2        0xe0
-
-/*
- * On read operations (page and oob-only), the first byte read from I/O reg is a
- * status.  On error, it reads 0x73; otherwise, it reads either 0x71 (first read
- * after reset only) or 0x51, so bit 1 is presumed to be an error indicator.
- */
-#define DOCG4_READ_ERROR           0x02 /* bit 1 indicates read error */
-
-/* anatomy of the device */
-#define DOCG4_CHIP_SIZE        0x8000000
-#define DOCG4_PAGE_SIZE        0x200
-#define DOCG4_PAGES_PER_BLOCK  0x200
-#define DOCG4_BLOCK_SIZE       (DOCG4_PAGES_PER_BLOCK * DOCG4_PAGE_SIZE)
-#define DOCG4_NUMBLOCKS        (DOCG4_CHIP_SIZE / DOCG4_BLOCK_SIZE)
-#define DOCG4_OOB_SIZE         0x10
-#define DOCG4_CHIP_SHIFT       27    /* log_2(DOCG4_CHIP_SIZE) */
-#define DOCG4_PAGE_SHIFT       9     /* log_2(DOCG4_PAGE_SIZE) */
-#define DOCG4_ERASE_SHIFT      18    /* log_2(DOCG4_BLOCK_SIZE) */
-
-/* all but the last byte is included in ecc calculation */
-#define DOCG4_BCH_SIZE         (DOCG4_PAGE_SIZE + DOCG4_OOB_SIZE - 1)
-
-#define DOCG4_USERDATA_LEN     520 /* 512 byte page plus 8 oob avail to user */
-
-/* expected values from the ID registers */
-#define DOCG4_IDREG1_VALUE     0x0400
-#define DOCG4_IDREG2_VALUE     0xfbff
-
-/* primitive polynomial used to build the Galois field used by hw ecc gen */
-#define DOCG4_PRIMITIVE_POLY   0x4443
-
-#define DOCG4_M                14  /* Galois field is of order 2^14 */
-#define DOCG4_T                4   /* BCH alg corrects up to 4 bit errors */
-
-#define DOCG4_FACTORY_BBT_PAGE 16 /* page where read-only factory bbt lives */
-
-#endif	/* __DOCG4_H__ */
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 9da77ec..cf20674 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -278,6 +278,11 @@
 	int usecount;
 };
 
+static inline int mtd_oobavail(struct mtd_info *mtd, struct mtd_oob_ops *ops)
+{
+	return ops->mode == MTD_OPS_AUTO_OOB ? mtd->oobavail : mtd->oobsize;
+}
+
 int mtd_erase(struct mtd_info *mtd, struct erase_info *instr);
 #ifndef __UBOOT__
 int mtd_point(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 23072fd..b5a02c3 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -25,6 +25,8 @@
 
 struct mtd_info;
 struct nand_flash_dev;
+struct device_node;
+
 /* Scan and identify a NAND device */
 extern int nand_scan(struct mtd_info *mtd, int max_chips);
 /*
@@ -144,6 +146,14 @@
 /* Enable Hardware ECC before syndrome is read back from flash */
 #define NAND_ECC_READSYN	2
 
+/*
+ * Enable generic NAND 'page erased' check. This check is only done when
+ * ecc.correct() returns -EBADMSG.
+ * Set this flag if your implementation does not fix bitflips in erased
+ * pages and you want to rely on the default implementation.
+ */
+#define NAND_ECC_GENERIC_ERASED_CHECK	BIT(0)
+
 /* Bit mask for flags passed to do_nand_read_ecc */
 #define NAND_GET_DEVICE		0x80
 
@@ -179,6 +189,12 @@
 /* Device supports subpage reads */
 #define NAND_SUBPAGE_READ	0x00001000
 
+/*
+ * Some MLC NANDs need data scrambling to limit bitflips caused by repeated
+ * patterns.
+ */
+#define NAND_NEED_SCRAMBLING	0x00002000
+
 /* Options valid for Samsung large page devices */
 #define NAND_SAMSUNG_LP_OPTIONS NAND_CACHEPRG
 
@@ -203,6 +219,11 @@
  * before calling nand_scan_tail.
  */
 #define NAND_BUSWIDTH_AUTO      0x00080000
+/*
+ * This option could be defined by controller drivers to protect against
+ * kmap'ed, vmalloc'ed highmem buffers being passed from upper layers
+ */
+#define NAND_USE_BOUNCE_BUFFER	0x00100000
 
 /* Options set by nand scan */
 /* bbt has already been read */
@@ -292,15 +313,15 @@
 	__le16 t_r;
 	__le16 t_ccs;
 	__le16 src_sync_timing_mode;
-	__le16 src_ssync_features;
+	u8 src_ssync_features;
 	__le16 clk_pin_capacitance_typ;
 	__le16 io_pin_capacitance_typ;
 	__le16 input_pin_capacitance_typ;
 	u8 input_pin_capacitance_max;
 	u8 driver_strength_support;
 	__le16 t_int_r;
-	__le16 t_ald;
-	u8 reserved4[7];
+	__le16 t_adl;
+	u8 reserved4[8];
 
 	/* vendor */
 	__le16 vendor_revision;
@@ -423,7 +444,7 @@
 	__le16 input_pin_capacitance_typ;
 	__le16 clk_pin_capacitance_typ;
 	u8 driver_strength_support;
-	__le16 t_ald;
+	__le16 t_adl;
 	u8 reserved4[36];
 
 	/* ECC and endurance block */
@@ -466,12 +487,19 @@
  * @total:	total number of ECC bytes per page
  * @prepad:	padding information for syndrome based ECC generators
  * @postpad:	padding information for syndrome based ECC generators
+ * @options:	ECC specific options (see NAND_ECC_XXX flags defined above)
  * @layout:	ECC layout control struct pointer
  * @priv:	pointer to private ECC control data
  * @hwctl:	function to control hardware ECC generator. Must only
  *		be provided if an hardware ECC is available
  * @calculate:	function for ECC calculation or readback from ECC hardware
- * @correct:	function for ECC correction, matching to ECC generator (sw/hw)
+ * @correct:	function for ECC correction, matching to ECC generator (sw/hw).
+ *		Should return a positive number representing the number of
+ *		corrected bitflips, -EBADMSG if the number of bitflips exceed
+ *		ECC strength, or any other error code if the error is not
+ *		directly related to correction.
+ *		If -EBADMSG is returned the input buffers should be left
+ *		untouched.
  * @read_page_raw:	function to read a raw page without ECC. This function
  *			should hide the specific layout used by the ECC
  *			controller and always return contiguous in-band and
@@ -509,6 +537,7 @@
 	int strength;
 	int prepad;
 	int postpad;
+	unsigned int options;
 	struct nand_ecclayout	*layout;
 	void *priv;
 	void (*hwctl)(struct mtd_info *mtd, int mode);
@@ -519,16 +548,16 @@
 	int (*read_page_raw)(struct mtd_info *mtd, struct nand_chip *chip,
 			uint8_t *buf, int oob_required, int page);
 	int (*write_page_raw)(struct mtd_info *mtd, struct nand_chip *chip,
-			const uint8_t *buf, int oob_required);
+			const uint8_t *buf, int oob_required, int page);
 	int (*read_page)(struct mtd_info *mtd, struct nand_chip *chip,
 			uint8_t *buf, int oob_required, int page);
 	int (*read_subpage)(struct mtd_info *mtd, struct nand_chip *chip,
 			uint32_t offs, uint32_t len, uint8_t *buf, int page);
 	int (*write_subpage)(struct mtd_info *mtd, struct nand_chip *chip,
 			uint32_t offset, uint32_t data_len,
-			const uint8_t *data_buf, int oob_required);
+			const uint8_t *data_buf, int oob_required, int page);
 	int (*write_page)(struct mtd_info *mtd, struct nand_chip *chip,
-			const uint8_t *buf, int oob_required);
+			const uint8_t *buf, int oob_required, int page);
 	int (*write_oob_raw)(struct mtd_info *mtd, struct nand_chip *chip,
 			int page);
 	int (*read_oob_raw)(struct mtd_info *mtd, struct nand_chip *chip,
@@ -556,6 +585,7 @@
 
 /**
  * struct nand_chip - NAND Private Flash Chip Data
+ * @mtd:		MTD device registered to the MTD framework
  * @IO_ADDR_R:		[BOARDSPECIFIC] address to read the 8 I/O lines of the
  *			flash device
  * @IO_ADDR_W:		[BOARDSPECIFIC] address to write the 8 I/O lines of the
@@ -571,10 +601,6 @@
  * @block_markbad:	[REPLACEABLE] mark a block bad
  * @cmd_ctrl:		[BOARDSPECIFIC] hardwarespecific function for controlling
  *			ALE/CLE/nCE. Also used to write command and address
- * @init_size:		[BOARDSPECIFIC] hardwarespecific function for setting
- *			mtd->oobsize, mtd->writesize and so on.
- *			@id_data contains the 8 bytes values of NAND_CMD_READID.
- *			Return with the bus width.
  * @dev_ready:		[BOARDSPECIFIC] hardwarespecific function for accessing
  *			device ready/busy line. If set to NULL no access to
  *			ready/busy is available and the ready/busy information
@@ -659,6 +685,7 @@
  */
 
 struct nand_chip {
+	struct mtd_info mtd;
 	void __iomem *IO_ADDR_R;
 	void __iomem *IO_ADDR_W;
 
@@ -668,11 +695,9 @@
 	void (*write_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
 	void (*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len);
 	void (*select_chip)(struct mtd_info *mtd, int chip);
-	int (*block_bad)(struct mtd_info *mtd, loff_t ofs, int getchip);
+	int (*block_bad)(struct mtd_info *mtd, loff_t ofs);
 	int (*block_markbad)(struct mtd_info *mtd, loff_t ofs);
 	void (*cmd_ctrl)(struct mtd_info *mtd, int dat, unsigned int ctrl);
-	int (*init_size)(struct mtd_info *mtd, struct nand_chip *this,
-			u8 *id_data);
 	int (*dev_ready)(struct mtd_info *mtd);
 	void (*cmdfunc)(struct mtd_info *mtd, unsigned command, int column,
 			int page_addr);
@@ -739,6 +764,26 @@
 	void *priv;
 };
 
+static inline struct nand_chip *mtd_to_nand(struct mtd_info *mtd)
+{
+	return container_of(mtd, struct nand_chip, mtd);
+}
+
+static inline struct mtd_info *nand_to_mtd(struct nand_chip *chip)
+{
+	return &chip->mtd;
+}
+
+static inline void *nand_get_controller_data(struct nand_chip *chip)
+{
+	return chip->priv;
+}
+
+static inline void nand_set_controller_data(struct nand_chip *chip, void *priv)
+{
+	chip->priv = priv;
+}
+
 /*
  * NAND Flash Manufacturer ID Codes
  */
@@ -852,7 +897,6 @@
 extern struct nand_flash_dev nand_flash_ids[];
 extern struct nand_manufacturers nand_manuf_ids[];
 
-extern int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd);
 extern int nand_default_bbt(struct mtd_info *mtd);
 extern int nand_markbad_bbt(struct mtd_info *mtd, loff_t offs);
 extern int nand_isreserved_bbt(struct mtd_info *mtd, loff_t offs);
@@ -877,7 +921,6 @@
  * @chip_delay:		R/B delay value in us
  * @options:		Option flags, e.g. 16bit buswidth
  * @bbt_options:	BBT option flags, e.g. NAND_BBT_USE_FLASH
- * @ecclayout:		ECC layout info structure
  * @part_probe_types:	NULL-terminated array of probe types
  */
 struct platform_nand_chip {
@@ -885,7 +928,6 @@
 	int chip_offset;
 	int nr_partitions;
 	struct mtd_partition *partitions;
-	struct nand_ecclayout *ecclayout;
 	int chip_delay;
 	unsigned int options;
 	unsigned int bbt_options;
@@ -934,15 +976,6 @@
 	struct platform_nand_ctrl ctrl;
 };
 
-/* Some helpers to access the data structures */
-static inline
-struct platform_nand_chip *get_platform_nandchip(struct mtd_info *mtd)
-{
-	struct nand_chip *chip = mtd->priv;
-
-	return chip->priv;
-}
-
 #ifdef CONFIG_SYS_NAND_ONFI_DETECTION
 /* return the supported features. */
 static inline int onfi_feature(struct nand_chip *chip)
@@ -1060,4 +1093,9 @@
 
 /* get timing characteristics from ONFI timing mode. */
 const struct nand_sdr_timings *onfi_async_timing_mode_to_sdr_timings(int mode);
+
+int nand_check_erased_ecc_chunk(void *data, int datalen,
+				void *ecc, int ecclen,
+				void *extraoob, int extraooblen,
+				int threshold);
 #endif /* __LINUX_MTD_NAND_H */
diff --git a/include/linux/mtd/nand_bch.h b/include/linux/mtd/nand_bch.h
index d8754dd..8ea6b04 100644
--- a/include/linux/mtd/nand_bch.h
+++ b/include/linux/mtd/nand_bch.h
@@ -32,9 +32,7 @@
 /*
  * Initialize BCH encoder/decoder
  */
-struct nand_bch_control *
-nand_bch_init(struct mtd_info *mtd, unsigned int eccsize,
-	      unsigned int eccbytes, struct nand_ecclayout **ecclayout);
+struct nand_bch_control *nand_bch_init(struct mtd_info *mtd);
 /*
  * Release BCH encoder/decoder resources
  */
@@ -55,12 +53,10 @@
 nand_bch_correct_data(struct mtd_info *mtd, unsigned char *buf,
 		      unsigned char *read_ecc, unsigned char *calc_ecc)
 {
-	return -1;
+	return -ENOTSUPP;
 }
 
-static inline struct nand_bch_control *
-nand_bch_init(struct mtd_info *mtd, unsigned int eccsize,
-	      unsigned int eccbytes, struct nand_ecclayout **ecclayout)
+static inline struct nand_bch_control *nand_bch_init(struct mtd_info *mtd)
 {
 	return NULL;
 }
diff --git a/include/linux/usb/xhci-fsl.h b/include/linux/usb/xhci-fsl.h
index c5e42e6..253eddf 100644
--- a/include/linux/usb/xhci-fsl.h
+++ b/include/linux/usb/xhci-fsl.h
@@ -59,10 +59,14 @@
 #define CONFIG_SYS_FSL_XHCI_USB1_ADDR CONFIG_SYS_LS2080A_XHCI_USB1_ADDR
 #define CONFIG_SYS_FSL_XHCI_USB2_ADDR CONFIG_SYS_LS2080A_XHCI_USB2_ADDR
 #define CONFIG_SYS_FSL_XHCI_USB3_ADDR 0
-#elif defined(CONFIG_LS1043A)
+#elif defined(CONFIG_LS1043A) || defined(CONFIG_LS1012A)
 #define CONFIG_SYS_FSL_XHCI_USB1_ADDR CONFIG_SYS_LS1043A_XHCI_USB1_ADDR
 #define CONFIG_SYS_FSL_XHCI_USB2_ADDR CONFIG_SYS_LS1043A_XHCI_USB2_ADDR
 #define CONFIG_SYS_FSL_XHCI_USB3_ADDR CONFIG_SYS_LS1043A_XHCI_USB3_ADDR
+#elif defined(CONFIG_LS1012A)
+#define CONFIG_SYS_FSL_XHCI_USB1_ADDR CONFIG_SYS_LS1043A_XHCI_USB1_ADDR
+#define CONFIG_SYS_FSL_XHCI_USB2_ADDR 0
+#define CONFIG_SYS_FSL_XHCI_USB3_ADDR 0
 #endif
 
 #define FSL_USB_XHCI_ADDR	{CONFIG_SYS_FSL_XHCI_USB1_ADDR, \
diff --git a/include/nand.h b/include/nand.h
index 7cbbbd3..a4f0f92 100644
--- a/include/nand.h
+++ b/include/nand.h
@@ -33,34 +33,36 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
 
+int nand_mtd_to_devnum(struct mtd_info *mtd);
+
 #ifdef CONFIG_SYS_NAND_SELF_INIT
 void board_nand_init(void);
-int nand_register(int devnum);
+int nand_register(int devnum, struct mtd_info *mtd);
 #else
 extern int board_nand_init(struct nand_chip *nand);
 #endif
 
-typedef struct mtd_info nand_info_t;
-
 extern int nand_curr_device;
-extern nand_info_t nand_info[];
+extern struct mtd_info *nand_info[];
 
-static inline int nand_read(nand_info_t *info, loff_t ofs, size_t *len, u_char *buf)
+static inline int nand_read(struct mtd_info *info, loff_t ofs, size_t *len,
+			    u_char *buf)
 {
 	return mtd_read(info, ofs, *len, (size_t *)len, buf);
 }
 
-static inline int nand_write(nand_info_t *info, loff_t ofs, size_t *len, u_char *buf)
+static inline int nand_write(struct mtd_info *info, loff_t ofs, size_t *len,
+			     u_char *buf)
 {
 	return mtd_write(info, ofs, *len, (size_t *)len, buf);
 }
 
-static inline int nand_block_isbad(nand_info_t *info, loff_t ofs)
+static inline int nand_block_isbad(struct mtd_info *info, loff_t ofs)
 {
 	return mtd_block_isbad(info, ofs);
 }
 
-static inline int nand_erase(nand_info_t *info, loff_t off, size_t size)
+static inline int nand_erase(struct mtd_info *info, loff_t off, size_t size)
 {
 	struct erase_info instr;
 
@@ -96,27 +98,28 @@
 
 typedef struct nand_erase_options nand_erase_options_t;
 
-int nand_read_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
+int nand_read_skip_bad(struct mtd_info *mtd, loff_t offset, size_t *length,
 		       size_t *actual, loff_t lim, u_char *buffer);
 
 #define WITH_DROP_FFS	(1 << 0) /* drop trailing all-0xff pages */
 #define WITH_WR_VERIFY	(1 << 1) /* verify data was written correctly */
 
-int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
+int nand_write_skip_bad(struct mtd_info *mtd, loff_t offset, size_t *length,
 			size_t *actual, loff_t lim, u_char *buffer, int flags);
-int nand_erase_opts(nand_info_t *meminfo, const nand_erase_options_t *opts);
-int nand_torture(nand_info_t *nand, loff_t offset);
-int nand_verify_page_oob(nand_info_t *nand, struct mtd_oob_ops *ops,
-			loff_t ofs);
-int nand_verify(nand_info_t *nand, loff_t ofs, size_t len, u_char *buf);
+int nand_erase_opts(struct mtd_info *mtd,
+		    const nand_erase_options_t *opts);
+int nand_torture(struct mtd_info *mtd, loff_t offset);
+int nand_verify_page_oob(struct mtd_info *mtd, struct mtd_oob_ops *ops,
+			 loff_t ofs);
+int nand_verify(struct mtd_info *mtd, loff_t ofs, size_t len, u_char *buf);
 
 #define NAND_LOCK_STATUS_TIGHT	0x01
 #define NAND_LOCK_STATUS_UNLOCK 0x04
 
-int nand_lock(nand_info_t *meminfo, int tight);
-int nand_unlock(nand_info_t *meminfo, loff_t start, size_t length,
-	int allexcept);
-int nand_get_lock_status(nand_info_t *meminfo, loff_t offset);
+int nand_lock(struct mtd_info *mtd, int tight);
+int nand_unlock(struct mtd_info *mtd, loff_t start, size_t length,
+		int allexcept);
+int nand_get_lock_status(struct mtd_info *mtd, loff_t offset);
 
 int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst);
 void nand_deselect(void);
@@ -135,6 +138,6 @@
 #define ENV_OOB_MARKER_OLD 0x30564e45 /*"ENV0" in little-endian -- offset is
 					stored as byte number */
 #define ENV_OFFSET_SIZE 8
-int get_nand_env_oob(nand_info_t *nand, unsigned long *result);
+int get_nand_env_oob(struct mtd_info *mtd, unsigned long *result);
 #endif
 int spl_nand_erase_one(int block, int page);
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index 70acc29..ab002e9 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -30,6 +30,7 @@
 	COMPAT(NVIDIA_TEGRA124_SOR, "nvidia,tegra124-sor"),
 	COMPAT(NVIDIA_TEGRA124_PMC, "nvidia,tegra124-pmc"),
 	COMPAT(NVIDIA_TEGRA20_DC, "nvidia,tegra20-dc"),
+	COMPAT(NVIDIA_TEGRA186_SDMMC, "nvidia,tegra186-sdhci"),
 	COMPAT(NVIDIA_TEGRA210_SDMMC, "nvidia,tegra210-sdhci"),
 	COMPAT(NVIDIA_TEGRA124_SDMMC, "nvidia,tegra124-sdhci"),
 	COMPAT(NVIDIA_TEGRA30_SDMMC, "nvidia,tegra30-sdhci"),
diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl
index 6d2017d..0997fd9 100644
--- a/scripts/Makefile.spl
+++ b/scripts/Makefile.spl
@@ -158,11 +158,8 @@
 ALL-y	+= boot.bin
 endif
 
-ifdef CONFIG_ARCH_ZYNQ
-ALL-y	+= $(obj)/boot.bin
-endif
-
-ALL-(CONFIG_ARCH_ZYNQMP)	+= $(obj)/boot.bin
+ALL-$(CONFIG_ARCH_ZYNQ)		+= $(obj)/boot.bin
+ALL-$(CONFIG_ARCH_ZYNQMP)	+= $(obj)/boot.bin
 
 all:	$(ALL-y)
 
diff --git a/test/dm/gpio.c b/test/dm/gpio.c
index 727db18..b994523 100644
--- a/test/dm/gpio.c
+++ b/test/dm/gpio.c
@@ -75,6 +75,13 @@
 	ut_assertok(ops->set_value(dev, offset, 1));
 	ut_asserteq(1, ops->get_value(dev, offset));
 
+	/* Make it an open drain output, and reset it */
+	ut_asserteq(0, sandbox_gpio_get_open_drain(dev, offset));
+	ut_assertok(ops->set_open_drain(dev, offset, 1));
+	ut_asserteq(1, sandbox_gpio_get_open_drain(dev, offset));
+	ut_assertok(ops->set_open_drain(dev, offset, 0));
+	ut_asserteq(0, sandbox_gpio_get_open_drain(dev, offset));
+
 	/* Make it an input */
 	ut_assertok(ops->direction_input(dev, offset));
 	ut_assertok(gpio_get_status(dev, offset, buf, sizeof(buf)));
diff --git a/tools/palmtreo680/flash_u-boot.c b/tools/palmtreo680/flash_u-boot.c
deleted file mode 100644
index 832d3fe..0000000
--- a/tools/palmtreo680/flash_u-boot.c
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright (C) 2013 Mike Dunn <mikedunn@newsguy.com>
- *
- * This file is released under the terms of GPL v2 and any later version.
- * See the file COPYING in the root directory of the source tree for details.
- *
- *
- * This is a userspace Linux utility that, when run on the Treo 680, will
- * program u-boot to flash.  The docg4 driver *must* be loaded with the
- * reliable_mode and ignore_badblocks parameters enabled:
- *
- *        modprobe docg4 ignore_badblocks=1 reliable_mode=1
- *
- * This utility writes the concatenated spl + u-boot image to the start of the
- * mtd device in the format expected by the IPL/SPL.  The image file and mtd
- * device node are passed to the utility as arguments.  The blocks must have
- * been erased beforehand.
- *
- * When you compile this, note that it links to libmtd from mtd-utils, so ensure
- * that your include and lib paths include this.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <string.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <errno.h>
-#include <mtd/mtd-user.h>
-#include "libmtd.h"
-
-#define RELIABLE_BLOCKSIZE  0x10000 /* block capacity in reliable mode */
-#define STANDARD_BLOCKSIZE  0x40000 /* block capacity in normal mode */
-#define PAGESIZE 512
-#define PAGES_PER_BLOCK 512
-#define OOBSIZE 7		/* available to user (16 total) */
-
-uint8_t ff_oob[OOBSIZE] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-
-/* this is the magic number the IPL looks for (ASCII "BIPO") */
-uint8_t page0_oob[OOBSIZE] = {'B', 'I', 'P', 'O', 0xff, 0xff, 0xff};
-
-int main(int argc, char * const argv[])
-{
-	int devfd, datafd, num_blocks, block;
-	off_t file_size;
-	libmtd_t mtd_desc;
-	struct mtd_dev_info devinfo;
-	uint8_t *blockbuf;
-	char response[8];
-
-	if (argc != 3) {
-		printf("usage: %s <image file> <mtd dev node>\n", argv[0]);
-		return -EINVAL;
-	}
-
-	mtd_desc = libmtd_open();
-	if (mtd_desc == NULL) {
-		int errsv = errno;
-		fprintf(stderr, "can't initialize libmtd\n");
-		return -errsv;
-	}
-
-	/* open the spl image file and mtd device */
-	datafd = open(argv[1], O_RDONLY);
-	if (datafd == -1) {
-		int errsv = errno;
-		perror(argv[1]);
-		return -errsv;
-	}
-	devfd = open(argv[2], O_WRONLY);
-	if (devfd == -1) {
-		int errsv = errno;
-		perror(argv[2]);
-		return -errsv;
-	}
-	if (mtd_get_dev_info(mtd_desc, argv[2], &devinfo) < 0) {
-		int errsv = errno;
-		perror(argv[2]);
-		return -errsv;
-	}
-
-	/* determine the number of blocks needed by the image */
-	file_size = lseek(datafd, 0, SEEK_END);
-	if (file_size == (off_t)-1) {
-		int errsv = errno;
-		perror("lseek");
-		return -errsv;
-	}
-	num_blocks = (file_size + RELIABLE_BLOCKSIZE - 1) / RELIABLE_BLOCKSIZE;
-	file_size = lseek(datafd, 0, SEEK_SET);
-	if (file_size == (off_t)-1) {
-		int errsv = errno;
-		perror("lseek");
-		return -errsv;
-	}
-	printf("The mtd partition contains %d blocks\n", devinfo.eb_cnt);
-	printf("U-Boot will occupy %d blocks\n", num_blocks);
-	if (num_blocks > devinfo.eb_cnt) {
-		fprintf(stderr, "Insufficient blocks on partition\n");
-		return -EINVAL;
-	}
-
-	printf("IMPORTANT: These blocks must be in an erased state!\n");
-	printf("Do you want to proceed?\n");
-	scanf("%s", response);
-	if ((response[0] != 'y') && (response[0] != 'Y')) {
-		printf("Exiting\n");
-		close(devfd);
-		close(datafd);
-		return 0;
-	}
-
-	blockbuf = calloc(RELIABLE_BLOCKSIZE, 1);
-	if (blockbuf == NULL) {
-		int errsv = errno;
-		perror("calloc");
-		return -errsv;
-	}
-
-	for (block = 0; block < num_blocks; block++) {
-		int ofs, page;
-		uint8_t *pagebuf = blockbuf, *buf = blockbuf;
-		uint8_t *oobbuf = page0_oob; /* magic num in oob of 1st page */
-		size_t len = RELIABLE_BLOCKSIZE;
-		int ret;
-
-		/* read data for one block from file */
-		while (len) {
-			ssize_t read_ret = read(datafd, buf, len);
-			if (read_ret == -1) {
-				int errsv = errno;
-				if (errno == EINTR)
-					continue;
-				perror("read");
-				return -errsv;
-			} else if (read_ret == 0) {
-				break; /* EOF */
-			}
-			len -= read_ret;
-			buf += read_ret;
-		}
-
-		printf("Block %d: writing\r", block + 1);
-		fflush(stdout);
-
-		for (page = 0, ofs = 0;
-		     page < PAGES_PER_BLOCK;
-		     page++, ofs += PAGESIZE) {
-			if (page & 0x04)  /* Odd-numbered 2k page */
-				continue; /* skipped in reliable mode */
-
-			ret = mtd_write(mtd_desc, &devinfo, devfd, block, ofs,
-					pagebuf, PAGESIZE, oobbuf, OOBSIZE,
-					MTD_OPS_PLACE_OOB);
-			if (ret) {
-				fprintf(stderr,
-					"\nmtd_write returned %d on block %d, ofs %x\n",
-					ret, block + 1, ofs);
-				return -EIO;
-			}
-			oobbuf = ff_oob;  /* oob for subsequent pages */
-
-			if (page & 0x01)  /* odd-numbered subpage */
-				pagebuf += PAGESIZE;
-		}
-	}
-
-	printf("\nDone\n");
-
-	close(devfd);
-	close(datafd);
-	free(blockbuf);
-	return 0;
-}