Merge branch 'master' of git://git.denx.de/u-boot-net
diff --git a/README b/README
index c0a9ea0..ef8d437 100644
--- a/README
+++ b/README
@@ -1472,8 +1472,8 @@
 		CONFIG_TPM
 		Support TPM devices.
 
-		CONFIG_TPM_TIS_I2C
-		Support for i2c bus TPM devices. Only one device
+		CONFIG_TPM_TIS_INFINEON
+		Support for Infineon i2c bus TPM devices. Only one device
 		per system is supported at this time.
 
 			CONFIG_TPM_TIS_I2C_BURST_LIMITATION
@@ -3494,6 +3494,10 @@
 		without a fastmap.
 		default: 0
 
+		CONFIG_MTD_UBI_FM_DEBUG
+		Enable UBI fastmap debug
+		default: 0
+
 - UBIFS support
 		CONFIG_CMD_UBIFS
 
diff --git a/arch/arm/dts/zynq-7000.dtsi b/arch/arm/dts/zynq-7000.dtsi
index 0b62cb0..84c15b5 100644
--- a/arch/arm/dts/zynq-7000.dtsi
+++ b/arch/arm/dts/zynq-7000.dtsi
@@ -191,6 +191,18 @@
 			#size-cells = <0>;
 		};
 
+		qspi: spi@e000d000 {
+			clock-names = "ref_clk", "pclk";
+			clocks = <&clkc 10>, <&clkc 43>;
+			compatible = "xlnx,zynq-qspi-1.0";
+			status = "disabled";
+			interrupt-parent = <&intc>;
+			interrupts = <0 19 4>;
+			reg = <0xe000d000 0x1000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
 		gem0: ethernet@e000b000 {
 			compatible = "cdns,zynq-gem", "cdns,gem";
 			reg = <0xe000b000 0x1000>;
diff --git a/arch/arm/dts/zynq-microzed.dts b/arch/arm/dts/zynq-microzed.dts
index c373a2c..d5e0050 100644
--- a/arch/arm/dts/zynq-microzed.dts
+++ b/arch/arm/dts/zynq-microzed.dts
@@ -14,6 +14,7 @@
 
 	aliases {
 		serial0 = &uart1;
+		spi0 = &qspi;
 	};
 
 	memory {
@@ -21,3 +22,7 @@
 		reg = <0 0x40000000>;
 	};
 };
+
+&qspi {
+	status = "okay";
+};
diff --git a/arch/arm/dts/zynq-zc702.dts b/arch/arm/dts/zynq-zc702.dts
index 6691a8d..4d86960 100644
--- a/arch/arm/dts/zynq-zc702.dts
+++ b/arch/arm/dts/zynq-zc702.dts
@@ -17,6 +17,7 @@
 		ethernet0 = &gem0;
 		i2c0 = &i2c0;
 		serial0 = &uart1;
+		spi0 = &qspi;
 	};
 
 	memory {
@@ -380,6 +381,10 @@
 	pinctrl-0 = <&pinctrl_uart1_default>;
 };
 
+&qspi {
+	status = "okay";
+};
+
 &usb0 {
 	status = "okay";
 	dr_mode = "host";
diff --git a/arch/arm/dts/zynq-zc706.dts b/arch/arm/dts/zynq-zc706.dts
index cf7bce4..fc336ea 100644
--- a/arch/arm/dts/zynq-zc706.dts
+++ b/arch/arm/dts/zynq-zc706.dts
@@ -17,6 +17,7 @@
 		ethernet0 = &gem0;
 		i2c0 = &i2c0;
 		serial0 = &uart1;
+		spi0 = &qspi;
 	};
 
 	memory {
@@ -301,6 +302,10 @@
 	pinctrl-0 = <&pinctrl_uart1_default>;
 };
 
+&qspi {
+	status = "okay";
+};
+
 &usb0 {
 	status = "okay";
 	dr_mode = "host";
diff --git a/arch/arm/dts/zynq-zc770-xm010.dts b/arch/arm/dts/zynq-zc770-xm010.dts
index 680f24c..cf56ac8 100644
--- a/arch/arm/dts/zynq-zc770-xm010.dts
+++ b/arch/arm/dts/zynq-zc770-xm010.dts
@@ -16,7 +16,8 @@
 		ethernet0 = &gem0;
 		i2c0 = &i2c0;
 		serial0 = &uart1;
-		spi0 = &spi1;
+		spi0 = &qspi;
+		spi1 = &spi1;
 	};
 
 	chosen {
@@ -53,6 +54,10 @@
 	};
 };
 
+&qspi {
+	status = "okay";
+};
+
 &can0 {
 	status = "okay";
 };
diff --git a/arch/arm/dts/zynq-zed.dts b/arch/arm/dts/zynq-zed.dts
index 5762576..3630490 100644
--- a/arch/arm/dts/zynq-zed.dts
+++ b/arch/arm/dts/zynq-zed.dts
@@ -16,6 +16,7 @@
 	aliases {
 		ethernet0 = &gem0;
 		serial0 = &uart1;
+		spi0 = &qspi;
 	};
 
 	memory {
@@ -56,6 +57,10 @@
 	status = "okay";
 };
 
+&qspi {
+	status = "okay";
+};
+
 &usb0 {
 	status = "okay";
 	dr_mode = "host";
diff --git a/arch/powerpc/cpu/ppc4xx/Kconfig b/arch/powerpc/cpu/ppc4xx/Kconfig
index ce58d86..945e771 100644
--- a/arch/powerpc/cpu/ppc4xx/Kconfig
+++ b/arch/powerpc/cpu/ppc4xx/Kconfig
@@ -28,9 +28,6 @@
 	select DM
 	select DM_SERIAL
 
-config TARGET_EBONY
-	bool "Support ebony"
-
 config TARGET_KATMAI
 	bool "Support katmai"
 
@@ -43,21 +40,12 @@
 config TARGET_MAKALU
 	bool "Support makalu"
 
-config TARGET_OCOTEA
-	bool "Support ocotea"
-
 config TARGET_REDWOOD
 	bool "Support redwood"
 
 config TARGET_SEQUOIA
 	bool "Support sequoia"
 
-config TARGET_TAIHU
-	bool "Support taihu"
-
-config TARGET_TAISHAN
-	bool "Support taishan"
-
 config TARGET_WALNUT
 	bool "Support walnut"
 
@@ -142,16 +130,12 @@
 source "board/amcc/bamboo/Kconfig"
 source "board/amcc/bubinga/Kconfig"
 source "board/amcc/canyonlands/Kconfig"
-source "board/amcc/ebony/Kconfig"
 source "board/amcc/katmai/Kconfig"
 source "board/amcc/kilauea/Kconfig"
 source "board/amcc/luan/Kconfig"
 source "board/amcc/makalu/Kconfig"
-source "board/amcc/ocotea/Kconfig"
 source "board/amcc/redwood/Kconfig"
 source "board/amcc/sequoia/Kconfig"
-source "board/amcc/taihu/Kconfig"
-source "board/amcc/taishan/Kconfig"
 source "board/amcc/walnut/Kconfig"
 source "board/amcc/yosemite/Kconfig"
 source "board/amcc/yucca/Kconfig"
diff --git a/board/amcc/ebony/Kconfig b/board/amcc/ebony/Kconfig
deleted file mode 100644
index ba73148..0000000
--- a/board/amcc/ebony/Kconfig
+++ /dev/null
@@ -1,16 +0,0 @@
-if TARGET_EBONY
-
-config SYS_BOARD
-	default "ebony"
-
-config SYS_VENDOR
-	default "amcc"
-
-config SYS_CONFIG_NAME
-	default "ebony"
-
-config DISPLAY_BOARDINFO
-	bool
-	default y
-
-endif
diff --git a/board/amcc/ebony/MAINTAINERS b/board/amcc/ebony/MAINTAINERS
deleted file mode 100644
index bc62851..0000000
--- a/board/amcc/ebony/MAINTAINERS
+++ /dev/null
@@ -1,6 +0,0 @@
-EBONY BOARD
-M:	Stefan Roese <sr@denx.de>
-S:	Maintained
-F:	board/amcc/ebony/
-F:	include/configs/ebony.h
-F:	configs/ebony_defconfig
diff --git a/board/amcc/ebony/Makefile b/board/amcc/ebony/Makefile
deleted file mode 100644
index 5876486..0000000
--- a/board/amcc/ebony/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-#
-# (C) Copyright 2002-2006
-# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
-#
-# SPDX-License-Identifier:	GPL-2.0+
-#
-
-obj-y	= ebony.o flash.o
-extra-y	+= init.o
diff --git a/board/amcc/ebony/README b/board/amcc/ebony/README
deleted file mode 100644
index 4df00b3..0000000
--- a/board/amcc/ebony/README
+++ /dev/null
@@ -1,136 +0,0 @@
-			   AMCC Ebony Board
-
-		    Last Update: September 12, 2002
-=======================================================================
-
-This file contains some handy info regarding U-Boot and the AMCC
-Ebony evaluation board. See the README.ppc440 for additional
-information.
-
-
-SWITCH SETTINGS & JUMPERS
-==========================
-
-Here's what I've been using successfully. If you feel inclined to
-change things ... please read the docs!
-
-DIPSW   U46         U80
-------------------------
-SW 1    off         on
-SW 2    on          on
-SW 3    on          on
-SW 4    off         on
-SW 5    on          off
-SW 6    on          on
-SW 7    on          off
-SW 8    on          off
-
-J41: strapped
-J42: open
-
-All others are factory default.
-
-
-I2C probe
-=====================
-
-The i2c utilities have been tested on both Rev B. and Rev C. and
-look good. The CONFIG_SYS_I2C_NOPROBES macro is defined to prevent
-probing the CDCV850 clock controller at address 0x69 (since reading
-it causes the i2c implementation to misbehave. The output of
-'i2c probe' should look like this (assuming you are only using a single
-SO-DIMM:
-
-=> i2c probe
-Valid chip addresses: 50 53 54
-Excluded chip addresses: 69
-
-
-GETTING OUT OF I2C TROUBLE
-===========================
-
-If you're like me ... you may have screwed up your bootstrap serial
-eeprom ... or worse, your SPD eeprom when experimenting with the
-i2c commands. If so, here are some ideas on how to get out of
-trouble:
-
-Serial bootstrap eeprom corruption:
------------------------------------
-Power down the board and set the following straps:
-
-J41 - open
-J42 - strapped
-
-This will select the default sys0 and sys1 settings (the serial
-eeproms are not used). Then power up the board and fix the serial
-eeprom using the 'i2c mm' command. Here are the values I currently
-use:
-
-=> i2c md 50 0 10
-0000: bf a2 04 01 ae 94 11 00 00 00 00 00 00 00 00 00    ................
-
-=> i2c md 54 0 10
-0000: 8f b3 24 01 4d 14 11 00 00 00 00 00 00 00 00 00    ..$.M...........
-
-Once you have the eeproms set correctly change the
-J41/J42 straps as you desire.
-
-SPD eeprom corruption:
-------------------------
-I've corrupted the SPD eeprom several times ... perhaps too much coffee
-and not enough presence of mind ;-). By default, the ebony code uses
-the SPD to initialize the DDR SDRAM control registers. So if the SPD
-eeprom is corrupted, U-Boot will never get into ram. Here's how I got
-out of this situation:
-
-0. First, _before_ playing with the i2c utilities, do an 'i2c probe', then
-use 'i2c md' to capture the various device contents to a file. Some day
-you may be glad you did this ... trust me :-). Otherwise try the
-following:
-
-1. In the include/configs/EBONY.h file find the line that defines
-the CONFIG_SPD_EEPROM macro and undefine it. E.g:
-
-#undef CONFIG_SPD_EEPROM
-
-This will make the code use default SDRAM control register
-settings without using the SPD eeprom.
-
-2. Rebuild U-Boot
-
-3. Load the new U-Boot image and reboot ebony.
-
-4. Repair the SPD eeprom using the 'i2c mm' command. Here's the eeprom
-contents that work with the default SO-DIMM that comes with the
-ebony board (micron 8VDDT164AG-265A1). Note: these are probably
-_not_ the factory settings ... but they work.
-
-=> i2c md 53 0 10 80
-0000: 80 08 07 0c 0a 01 40 00 04 75 75 00 80 08 00 01    ......@..uu.....
-0010: 0e 04 0c 01 02 20 00 a0 75 00 00 50 3c 50 2d 20    ..... ..u..P<P-
-0020: 90 90 50 50 00 00 00 00 00 41 4b 34 32 75 00 00    ..PP.....AK42u..
-0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 9c    ................
-0040: 2c 00 00 00 00 00 00 00 08 38 56 44 44 54 31 36    ,........8VDDT16
-0050: 36 34 41 47 2d 32 36 35 41 31 20 01 00 01 2c 63    64AG-265A1 ...,c
-0060: 22 25 ab 00 00 00 00 00 00 00 00 00 00 00 00 00    "%..............
-0070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
-
-
-PCI DOUBLE-ENUMERATION WOES
-===========================
-
-If you're not using PCI-X cards and are simply using 32-bit and/or
-33 MHz cards via extenders and the like, you may notice that the
-initial pci scan reports various devices twice ... and configuration
-does not succeed (one or more devices are enumerated twice). To correct
-this we replaced the 2K ohm resistor on the IDSEL line(s) with a
-22 ohm resistor and the problem went away. This change hasn't broken
-anything yet -- use at your own risk.
-
-We never tested anything other than 33 MHz/32-bit cards. If you have
-the chance to do this, please let me know how things turn out :-)
-
-
-Regards,
---Scott
-<smcnutt@artesyncp.com>
diff --git a/board/amcc/ebony/config.mk b/board/amcc/ebony/config.mk
deleted file mode 100644
index f18b097..0000000
--- a/board/amcc/ebony/config.mk
+++ /dev/null
@@ -1,16 +0,0 @@
-#
-# (C) Copyright 2002
-# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
-#
-# SPDX-License-Identifier:	GPL-2.0+
-#
-
-PLATFORM_CPPFLAGS += -DCONFIG_440=1
-
-ifeq ($(debug),1)
-PLATFORM_CPPFLAGS += -DDEBUG
-endif
-
-ifeq ($(dbcr),1)
-PLATFORM_CPPFLAGS += -DCONFIG_SYS_INIT_DBCR=0x8cff0000
-endif
diff --git a/board/amcc/ebony/ebony.c b/board/amcc/ebony/ebony.c
deleted file mode 100644
index eb42448..0000000
--- a/board/amcc/ebony/ebony.c
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- *  Copyright (C) 2002 Scott McNutt <smcnutt@artesyncp.com>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <common.h>
-#include <asm/processor.h>
-#include <spd_sdram.h>
-
-#define BOOT_SMALL_FLASH	32	/* 00100000 */
-#define FLASH_ONBD_N		2	/* 00000010 */
-#define FLASH_SRAM_SEL		1	/* 00000001 */
-
-DECLARE_GLOBAL_DATA_PTR;
-
-long int fixed_sdram(void);
-
-int board_early_init_f(void)
-{
-	uint reg;
-	unsigned char *fpga_base = (unsigned char *)CONFIG_SYS_FPGA_BASE;
-	unsigned char status;
-
-	/*--------------------------------------------------------------------
-	 * Setup the external bus controller/chip selects
-	 *-------------------------------------------------------------------*/
-	mtdcr(EBC0_CFGADDR, EBC0_CFG);
-	reg = mfdcr(EBC0_CFGDATA);
-	mtdcr(EBC0_CFGDATA, reg | 0x04000000);	/* Set ATC */
-
-	mtebc(PB1AP, 0x02815480);	/* NVRAM/RTC */
-	mtebc(PB1CR, 0x48018000);	/* BA=0x480 1MB R/W 8-bit */
-	mtebc(PB7AP, 0x01015280);	/* FPGA registers */
-	mtebc(PB7CR, 0x48318000);	/* BA=0x483 1MB R/W 8-bit */
-
-	/* read FPGA_REG0  and set the bus controller */
-	status = *fpga_base;
-	if ((status & BOOT_SMALL_FLASH) && !(status & FLASH_ONBD_N)) {
-		mtebc(PB0AP, 0x9b015480);	/* FLASH/SRAM */
-		mtebc(PB0CR, 0xfff18000);	/* BAS=0xfff 1MB R/W 8-bit */
-		mtebc(PB2AP, 0x9b015480);	/* 4MB FLASH */
-		mtebc(PB2CR, 0xff858000);	/* BAS=0xff8 4MB R/W 8-bit */
-	} else {
-		mtebc(PB0AP, 0x9b015480);	/* 4MB FLASH */
-		mtebc(PB0CR, 0xffc58000);	/* BAS=0xffc 4MB R/W 8-bit */
-
-		/* set CS2 if FLASH_ONBD_N == 0 */
-		if (!(status & FLASH_ONBD_N)) {
-			mtebc(PB2AP, 0x9b015480);	/* FLASH/SRAM */
-			mtebc(PB2CR, 0xff818000);	/* BAS=0xff8 4MB R/W 8-bit */
-		}
-	}
-
-	/*--------------------------------------------------------------------
-	 * Setup the interrupt controller polarities, triggers, etc.
-	 *-------------------------------------------------------------------*/
-	mtdcr(UIC0SR, 0xffffffff);	/* clear all */
-	mtdcr(UIC0ER, 0x00000000);	/* disable all */
-	mtdcr(UIC0CR, 0x00000009);	/* SMI & UIC1 crit are critical */
-	mtdcr(UIC0PR, 0xfffffe13);	/* per ref-board manual */
-	mtdcr(UIC0TR, 0x01c00008);	/* per ref-board manual */
-	mtdcr(UIC0VR, 0x00000001);	/* int31 highest, base=0x000 */
-	mtdcr(UIC0SR, 0xffffffff);	/* clear all */
-
-	mtdcr(UIC1SR, 0xffffffff);	/* clear all */
-	mtdcr(UIC1ER, 0x00000000);	/* disable all */
-	mtdcr(UIC1CR, 0x00000000);	/* all non-critical */
-	mtdcr(UIC1PR, 0xffffe0ff);	/* per ref-board manual */
-	mtdcr(UIC1TR, 0x00ffc000);	/* per ref-board manual */
-	mtdcr(UIC1VR, 0x00000001);	/* int31 highest, base=0x000 */
-	mtdcr(UIC1SR, 0xffffffff);	/* clear all */
-
-	return 0;
-}
-
-int checkboard(void)
-{
-	char buf[64];
-	int i = getenv_f("serial#", buf, sizeof(buf));
-
-	printf("Board: Ebony - AMCC PPC440GP Evaluation Board");
-	if (i > 0) {
-		puts(", serial# ");
-		puts(buf);
-	}
-	putc('\n');
-
-	return (0);
-}
-
-phys_size_t initdram(int board_type)
-{
-	long dram_size = 0;
-
-#if defined(CONFIG_SPD_EEPROM)
-	dram_size = spd_sdram();
-#else
-	dram_size = fixed_sdram();
-#endif
-	return dram_size;
-}
-
-#if !defined(CONFIG_SPD_EEPROM)
-/*************************************************************************
- *  fixed sdram init -- doesn't use serial presence detect.
- *
- *  Assumes:    128 MB, non-ECC, non-registered
- *              PLB @ 133 MHz
- *
- ************************************************************************/
-long int fixed_sdram(void)
-{
-	uint reg;
-
-	/*--------------------------------------------------------------------
-	 * Setup some default
-	 *------------------------------------------------------------------*/
-	mtsdram(SDRAM0_UABBA, 0x00000000);	/* ubba=0 (default)             */
-	mtsdram(SDRAM0_SLIO, 0x00000000);	/* rdre=0 wrre=0 rarw=0         */
-	mtsdram(SDRAM0_DEVOPT, 0x00000000);	/* dll=0 ds=0 (normal)          */
-	mtsdram(SDRAM0_WDDCTR, 0x00000000);	/* wrcp=0 dcd=0                 */
-	mtsdram(SDRAM0_CLKTR, 0x40000000);	/* clkp=1 (90 deg wr) dcdt=0    */
-
-	/*--------------------------------------------------------------------
-	 * Setup for board-specific specific mem
-	 *------------------------------------------------------------------*/
-	/*
-	 * Following for CAS Latency = 2.5 @ 133 MHz PLB
-	 */
-	mtsdram(SDRAM0_B0CR, 0x000a4001);	/* SDBA=0x000 128MB, Mode 3, enabled */
-	mtsdram(SDRAM0_TR0, 0x410a4012);	/* WR=2  WD=1 CL=2.5 PA=3 CP=4 LD=2 */
-	/* RA=10 RD=3                       */
-	mtsdram(SDRAM0_TR1, 0x8080082f);	/* SS=T2 SL=STAGE 3 CD=1 CT=0x02f   */
-	mtsdram(SDRAM0_RTR, 0x08200000);	/* Rate 15.625 ns @ 133 MHz PLB     */
-	mtsdram(SDRAM0_CFG1, 0x00000000);	/* Self-refresh exit, disable PM    */
-	udelay(400);		/* Delay 200 usecs (min)            */
-
-	/*--------------------------------------------------------------------
-	 * Enable the controller, then wait for DCEN to complete
-	 *------------------------------------------------------------------*/
-	mtsdram(SDRAM0_CFG0, 0x86000000);	/* DCEN=1, PMUD=1, 64-bit           */
-	for (;;) {
-		mfsdram(SDRAM0_MCSTS, reg);
-		if (reg & 0x80000000)
-			break;
-	}
-
-	return (128 * 1024 * 1024);	/* 128 MB                           */
-}
-#endif				/* !defined(CONFIG_SPD_EEPROM) */
diff --git a/board/amcc/ebony/flash.c b/board/amcc/ebony/flash.c
deleted file mode 100644
index 5740a56..0000000
--- a/board/amcc/ebony/flash.c
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * (C) Copyright 2002
- * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
- *
- * (C) Copyright 2002 Jun Gu <jung@artesyncp.com>
- * Add support for Am29F016D and dynamic switch setting.
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-/*
- * Modified 4/5/2001
- * Wait for completion of each sector erase command issued
- * 4/5/2001
- * Chris Hallinan - DS4.COM, Inc. - clh@net1plus.com
- */
-
-#include <common.h>
-#include <asm/ppc4xx.h>
-#include <asm/processor.h>
-#include <asm/io.h>
-
-#undef DEBUG
-#ifdef DEBUG
-#define DEBUGF(x...) printf(x)
-#else
-#define DEBUGF(x...)
-#endif				/* DEBUG */
-
-#define     BOOT_SMALL_FLASH        32	/* 00100000 */
-#define     FLASH_ONBD_N            2	/* 00000010 */
-#define     FLASH_SRAM_SEL          1	/* 00000001 */
-
-#define     BOOT_SMALL_FLASH_VAL    4
-#define     FLASH_ONBD_N_VAL        2
-#define     FLASH_SRAM_SEL_VAL      1
-
-static unsigned long flash_addr_table[8][CONFIG_SYS_MAX_FLASH_BANKS] = {
-	{0xffc00000, 0xffe00000, 0xff880000},	/* 0:000: configuraton 3 */
-	{0xffc00000, 0xffe00000, 0xff800000},	/* 1:001: configuraton 4 */
-	{0xffc00000, 0xffe00000, 0x00000000},	/* 2:010: configuraton 7 */
-	{0xffc00000, 0xffe00000, 0x00000000},	/* 3:011: configuraton 8 */
-	{0xff800000, 0xffa00000, 0xfff80000},	/* 4:100: configuraton 1 */
-	{0xff800000, 0xffa00000, 0xfff00000},	/* 5:101: configuraton 2 */
-	{0xffc00000, 0xffe00000, 0x00000000},	/* 6:110: configuraton 5 */
-	{0xffc00000, 0xffe00000, 0x00000000}	/* 7:111: configuraton 6 */
-};
-
-/*
- * include common flash code (for amcc boards)
- */
-#include "../common/flash.c"
-
-/*-----------------------------------------------------------------------
- * Functions
- */
-static ulong flash_get_size(vu_long * addr, flash_info_t * info);
-
-/*
- * Override the weak default mapping function with a board specific one
- */
-u32 flash_get_bank_size(int cs, int idx)
-{
-	u8 reg = in_8((void *)CONFIG_SYS_FPGA_BASE);
-
-	if ((reg & BOOT_SMALL_FLASH) && !(reg & FLASH_ONBD_N)) {
-		/*
-		 * cs0: small flash (512KiB)
-		 * cs2: 2 * big flash (2 * 2MiB)
-		 */
-		if (cs == 0)
-			return flash_info[2].size;
-		if (cs == 2)
-			return flash_info[0].size + flash_info[1].size;
-	} else {
-		/*
-		 * cs0: 2 * big flash (2 * 2MiB)
-		 * cs2: small flash (512KiB)
-		 */
-		if (cs == 0)
-			return flash_info[0].size + flash_info[1].size;
-		if (cs == 2)
-			return flash_info[2].size;
-	}
-
-	return 0;
-}
-
-unsigned long flash_init(void)
-{
-	unsigned long total_b = 0;
-	unsigned long size_b[CONFIG_SYS_MAX_FLASH_BANKS];
-	unsigned char *fpga_base = (unsigned char *)CONFIG_SYS_FPGA_BASE;
-	unsigned char switch_status;
-	unsigned short index = 0;
-	int i;
-
-	/* read FPGA base register FPGA_REG0 */
-	switch_status = *fpga_base;
-
-	/* check the bitmap of switch status */
-	if (switch_status & BOOT_SMALL_FLASH) {
-		index += BOOT_SMALL_FLASH_VAL;
-	}
-	if (switch_status & FLASH_ONBD_N) {
-		index += FLASH_ONBD_N_VAL;
-	}
-	if (switch_status & FLASH_SRAM_SEL) {
-		index += FLASH_SRAM_SEL_VAL;
-	}
-
-	DEBUGF("\n");
-	DEBUGF("FLASH: Index: %d\n", index);
-
-	/* Init: no FLASHes known */
-	for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
-		flash_info[i].flash_id = FLASH_UNKNOWN;
-		flash_info[i].sector_count = -1;
-		flash_info[i].size = 0;
-
-		/* check whether the address is 0 */
-		if (flash_addr_table[index][i] == 0) {
-			continue;
-		}
-
-		/* call flash_get_size() to initialize sector address */
-		size_b[i] = flash_get_size((vu_long *)
-					   flash_addr_table[index][i],
-					   &flash_info[i]);
-		flash_info[i].size = size_b[i];
-		if (flash_info[i].flash_id == FLASH_UNKNOWN) {
-			printf("## Unknown FLASH on Bank %d - Size = 0x%08lx = %ld MB\n",
-			       i, size_b[i], size_b[i] << 20);
-			flash_info[i].sector_count = -1;
-			flash_info[i].size = 0;
-		}
-
-		/* Monitor protection ON by default */
-		(void)flash_protect(FLAG_PROTECT_SET, CONFIG_SYS_MONITOR_BASE,
-				    CONFIG_SYS_MONITOR_BASE + CONFIG_SYS_MONITOR_LEN - 1,
-				    &flash_info[2]);
-#ifdef CONFIG_ENV_IS_IN_FLASH
-		(void)flash_protect(FLAG_PROTECT_SET, CONFIG_ENV_ADDR,
-				    CONFIG_ENV_ADDR + CONFIG_ENV_SECT_SIZE - 1,
-				    &flash_info[2]);
-		(void)flash_protect(FLAG_PROTECT_SET, CONFIG_ENV_ADDR_REDUND,
-				    CONFIG_ENV_ADDR_REDUND + CONFIG_ENV_SECT_SIZE - 1,
-				    &flash_info[2]);
-#endif
-
-		total_b += flash_info[i].size;
-	}
-
-	return total_b;
-}
diff --git a/board/amcc/ebony/init.S b/board/amcc/ebony/init.S
deleted file mode 100644
index 904e648..0000000
--- a/board/amcc/ebony/init.S
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
-*  Copyright (C) 2002 Scott McNutt <smcnutt@artesyncp.com>
- * SPDX-License-Identifier:	GPL-2.0+
-*/
-
-#include <ppc_asm.tmpl>
-#include <config.h>
-#include <asm/mmu.h>
-#include <asm/ppc4xx.h>
-
-/**************************************************************************
- * TLB TABLE
- *
- * This table is used by the cpu boot code to setup the initial tlb
- * entries. Rather than make broad assumptions in the cpu source tree,
- * this table lets each board set things up however they like.
- *
- *  Pointer to the table is returned in r1
- *
- *************************************************************************/
-
-	.section .bootpg,"ax"
-	.globl tlbtab
-
-tlbtab:
-	tlbtab_start
-
-	tlbentry(0xf0000000, SZ_256M, 0xf0000000, 1, AC_RWX | SA_IG)
-
-	/*
-	 * TLB entries for SDRAM are not needed on this platform.
-	 * They are dynamically generated in the SPD DDR(2) detection
-	 * routine.
-	 */
-
-	tlbentry(CONFIG_SYS_PERIPHERAL_BASE, SZ_256M, 0x40000000, 1, AC_RW | SA_IG)
-	tlbentry(CONFIG_SYS_ISRAM_BASE, SZ_4K, 0x80000000, 0, AC_RWX)
-	tlbentry(CONFIG_SYS_ISRAM_BASE + 0x1000, SZ_4K, 0x80001000, 0, AC_RWX)
-	tlbentry(CONFIG_SYS_PCI_BASE, SZ_256M, 0x00000000, 2, AC_RW | SA_IG)
-	tlbentry(CONFIG_SYS_PCI_MEMBASE, SZ_256M, 0x00000000, 3, AC_RW | SA_IG)
-	tlbtab_end
diff --git a/board/amcc/ocotea/Kconfig b/board/amcc/ocotea/Kconfig
deleted file mode 100644
index 489e8a4..0000000
--- a/board/amcc/ocotea/Kconfig
+++ /dev/null
@@ -1,16 +0,0 @@
-if TARGET_OCOTEA
-
-config SYS_BOARD
-	default "ocotea"
-
-config SYS_VENDOR
-	default "amcc"
-
-config SYS_CONFIG_NAME
-	default "ocotea"
-
-config DISPLAY_BOARDINFO
-	bool
-	default y
-
-endif
diff --git a/board/amcc/ocotea/MAINTAINERS b/board/amcc/ocotea/MAINTAINERS
deleted file mode 100644
index 34634a2..0000000
--- a/board/amcc/ocotea/MAINTAINERS
+++ /dev/null
@@ -1,6 +0,0 @@
-OCOTEA BOARD
-M:	Stefan Roese <sr@denx.de>
-S:	Maintained
-F:	board/amcc/ocotea/
-F:	include/configs/ocotea.h
-F:	configs/ocotea_defconfig
diff --git a/board/amcc/ocotea/Makefile b/board/amcc/ocotea/Makefile
deleted file mode 100644
index 7646bbb..0000000
--- a/board/amcc/ocotea/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-#
-# (C) Copyright 2002-2006
-# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
-#
-# SPDX-License-Identifier:	GPL-2.0+
-#
-
-obj-y	= ocotea.o flash.o
-extra-y	+= init.o
diff --git a/board/amcc/ocotea/README.ocotea b/board/amcc/ocotea/README.ocotea
deleted file mode 100644
index be79b03..0000000
--- a/board/amcc/ocotea/README.ocotea
+++ /dev/null
@@ -1,73 +0,0 @@
-			   AMCC Ocotea Board
-
-		    Last Update: March 2, 2004
-=======================================================================
-
-This file contains some handy info regarding U-Boot and the AMCC
-Ocotea 440gx  evaluation board. See the README.ppc440 for additional
-information.
-
-
-SWITCH SETTINGS & JUMPERS
-==========================
-
-Here's what I've been using successfully. If you feel inclined to
-change things ... please read the docs!
-
-DIPSW   U46         U80
-------------------------
-SW 1    off         off
-SW 2    on          off
-SW 3    off         off
-SW 4    off         off
-SW 5    off         off
-SW 6    on          on
-SW 7    on          off
-SW 8    on          off
-
-J41: strapped
-J42: open
-
-All others are factory default.
-
-
-I2C Information
-=====================
-
-See README.ebony for information.
-
-PCI
-===========================
-
-Untested at the time of writing.
-
-PPC440GX Ethernet EMACs
-===========================
-
-All EMAC ports have been tested and are known to work
-with EPS Group 4.
-
-Special note about the Cicada CIS8201:
-	The CIS8201 Gigabit PHY comes up in GMII mode by default.
-	One must hit an extended register to allow use of RGMII mode.
-	This has been done in the 440gx_enet.c file with a #ifdef/endif
-	pair.
-
-AMCC does not store the EMAC ethernet addresses within their PIBS bootloader.
-The addresses contained in the config header file are from my particular
-board and you _*should*_ change them to reflect your board either in the
-config file and/or in your environment variables.  I found the addresses on
-labels on the bottom side of the board.
-
-
-BDI2k or JTAG Debugging
-===========================
-
-For ease of debugging you can swap the small boot flash and external SRAM
-by changing U46:3 to on.  You can then use the sram as your boot flash by
-loading the sram via the jtag debugger.
-
-
-Regards,
---Travis
-<tsawyer@sandburst.com>
diff --git a/board/amcc/ocotea/README.ocotea-PIBS-to-U-Boot b/board/amcc/ocotea/README.ocotea-PIBS-to-U-Boot
deleted file mode 100644
index 25dd2a2..0000000
--- a/board/amcc/ocotea/README.ocotea-PIBS-to-U-Boot
+++ /dev/null
@@ -1,99 +0,0 @@
-------------------------------------------
-Installation of U-Boot using PIBS firmware
-------------------------------------------
-
-This document describes how to install U-Boot on the Ocotea PPC440GX
-Evaluation Board. We do not erase the PIBS firmware but install U-Boot in the
-soldered FLASH. After this you should be able to switch between PIBS and
-U-Boot via the switch U46 SW1. Please check that SW1 is off (= open) before
-continuing.
-
-Connect to the serial port 0 (J11 lower) of the Ocotea board using the cu
-program. See the hints for configuring cu above. Make sure you can
-communicate with the PIBS firmware: reset the board and hit ENTER a couple of
-times until you see the PIBS prompt (PIBS $). Then proceed as follows:
-
-
-Read MAC Addresses from PIBS
-----------------------------
-
-To read the configured MAC addresses available on your Ocotea board please use
-the following commands:
-
-PIBS $ echo $hwdaddr0
-000173017FE3
-PIBS $ echo $hwdaddr1
-000173017FE4
-PIBS $ echo $hwdaddr2
-000173017FE1
-PIBS $ echo $hwdaddr3
-000173017FE2
-
-In U-Boot this is stored in the following environment variables:
-
-* Ethernet Address 0: ethaddr = 000173017FE3 (==> 00:01:73:01:7F:E3)
-* Ethernet Address 1: eth1addr = 000173017FE4 (==> 00:01:73:01:7F:E4)
-* Ethernet Address 2: eth2addr = 000173017FE1 (==> 00:01:73:01:7F:E1)
-* Ethernet Address 3: eth3addr = 000173017FE2 (==> 00:01:73:01:7F:E2)
-
-
-Configure the network interface (ent0 == emac0)
------------------------------------------------
-
-To download the U-Boot image we need to configure the ethernet interface with
-the following commands:
-
-PIBS $ ifconfig ent0 192.168.160.142 netmask 255.255.0.0 up
-PIBS $ set ipdstaddr0=192.168.1.1
-status: writing PIBS variable value to FLASH
-PIBS $ set bootfilename=/tftpboot/ocotea/u-boot.bin
-status: writing PIBS variable value to FLASH
-
-Please insert correct parameters for your configuration (ip-addresses and
-file-location).
-
-
-Program U-Boot into soldered User-FLASH
----------------------------------------
-
-Please make sure to use a newer version of U-Boot (at least 1.1.3), since
-older versions don't support running from user-FLASH.
-
-To program U-Boot into the soldered user-FLASH use the following command:
-
-PIBS $ storefile bin eth 0xffbc0000
-
-This commands loads the file vis ethernet into ram and copies it into the
-user-FLASH.
-
-
-Switch to U-Boot
-----------------
-
-Now you can turn your board off and switch SW1 (U46) to on (= closed). After
-powering the board you should see the following message:
-
-U-Boot 1.1.3 (Apr  5 2005 - 22:59:57)
-
-AMCC PowerPC 440 GX Rev. C
-Board: AMCC 440GX Evaluation Board
-	VCO: 1066 MHz
-	CPU: 533 MHz
-	PLB: 152 MHz
-	OPB: 76 MHz
-	EPB: 76 MHz
-I2C:   ready
-DRAM:  256 MB
-FLASH:	5 MB
-PCI:   Bus Dev VenId DevId Class Int
-In:    serial
-Out:   serial
-Err:   serial
-KGDB:  kgdb ready
-ready
-Net:   ppc_440x_eth0, ppc_440x_eth1, ppc_440x_eth2, ppc_440x_eth3
-BEDBUG:ready
-=>
-
-
-April 06 2005, Stefan Roese <sr@denx.de>
diff --git a/board/amcc/ocotea/config.mk b/board/amcc/ocotea/config.mk
deleted file mode 100644
index e19b561..0000000
--- a/board/amcc/ocotea/config.mk
+++ /dev/null
@@ -1,20 +0,0 @@
-#
-# (C) Copyright 2004
-# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
-#
-# SPDX-License-Identifier:	GPL-2.0+
-#
-
-#
-# AMCC 440GX Reference Platform (Ocotea) board
-#
-
-PLATFORM_CPPFLAGS += -DCONFIG_440=1
-
-ifeq ($(debug),1)
-PLATFORM_CPPFLAGS += -DDEBUG
-endif
-
-ifeq ($(dbcr),1)
-PLATFORM_CPPFLAGS += -DCONFIG_SYS_INIT_DBCR=0x8cff0000
-endif
diff --git a/board/amcc/ocotea/flash.c b/board/amcc/ocotea/flash.c
deleted file mode 100644
index a9bbf04..0000000
--- a/board/amcc/ocotea/flash.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * (C) Copyright 2004-2005
- * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
- *
- * (C) Copyright 2002 Jun Gu <jung@artesyncp.com>
- * Add support for Am29F016D and dynamic switch setting.
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-/*
- * Modified 4/5/2001
- * Wait for completion of each sector erase command issued
- * 4/5/2001
- * Chris Hallinan - DS4.COM, Inc. - clh@net1plus.com
- */
-
-#include <common.h>
-#include <asm/ppc4xx.h>
-#include <asm/processor.h>
-
-#undef DEBUG
-
-#ifdef DEBUG
-#define DEBUGF(x...) printf(x)
-#else
-#define DEBUGF(x...)
-#endif				/* DEBUG */
-
-#define     BOOT_SMALL_FLASH        0x40	/* 01000000 */
-#define     FLASH_ONBD_N            2	/* 00000010 */
-#define     FLASH_SRAM_SEL          1	/* 00000001 */
-#define     FLASH_ONBD_N            2	/* 00000010 */
-#define     FLASH_SRAM_SEL          1	/* 00000001 */
-
-#define     BOOT_SMALL_FLASH_VAL    4
-#define     FLASH_ONBD_N_VAL        2
-#define     FLASH_SRAM_SEL_VAL      1
-
-flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];	/* info for FLASH chips        */
-
-static unsigned long flash_addr_table[8][CONFIG_SYS_MAX_FLASH_BANKS] = {
-	{0xFF800000, 0xFF880000, 0xFFC00000},	/* 0:000: configuraton 4 */
-	{0xFF900000, 0xFF980000, 0xFFC00000},	/* 1:001: configuraton 3 */
-	{0x00000000, 0x00000000, 0x00000000},	/* 2:010: configuraton 8 */
-	{0x00000000, 0x00000000, 0x00000000},	/* 3:011: configuraton 7 */
-	{0xFFE00000, 0xFFF00000, 0xFF800000},	/* 4:100: configuraton 2 */
-	{0xFFF00000, 0xFFF80000, 0xFF800000},	/* 5:101: configuraton 1 */
-	{0x00000000, 0x00000000, 0x00000000},	/* 6:110: configuraton 6 */
-	{0x00000000, 0x00000000, 0x00000000}	/* 7:111: configuraton 5 */
-};
-
-/*
- * include common flash code (for amcc boards)
- */
-#include "../common/flash.c"
-
-/*-----------------------------------------------------------------------
- * Functions
- */
-static ulong flash_get_size(vu_long * addr, flash_info_t * info);
-static int write_word(flash_info_t * info, ulong dest, ulong data);
-
-/*-----------------------------------------------------------------------
- */
-
-unsigned long flash_init(void)
-{
-	unsigned long total_b = 0;
-	unsigned long size_b[CONFIG_SYS_MAX_FLASH_BANKS];
-	unsigned char *fpga_base = (unsigned char *)CONFIG_SYS_FPGA_BASE;
-	unsigned char switch_status;
-	unsigned short index = 0;
-	int i;
-
-	/* read FPGA base register FPGA_REG0 */
-	switch_status = *fpga_base;
-
-	/* check the bitmap of switch status */
-	if (switch_status & BOOT_SMALL_FLASH) {
-		index += BOOT_SMALL_FLASH_VAL;
-	}
-	if (switch_status & FLASH_ONBD_N) {
-		index += FLASH_ONBD_N_VAL;
-	}
-	if (switch_status & FLASH_SRAM_SEL) {
-		index += FLASH_SRAM_SEL_VAL;
-	}
-
-	DEBUGF("\n");
-	DEBUGF("FLASH: Index: %d\n", index);
-
-	/* Init: no FLASHes known */
-	for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
-		flash_info[i].flash_id = FLASH_UNKNOWN;
-		flash_info[i].sector_count = -1;
-		flash_info[i].size = 0;
-
-		/* check whether the address is 0 */
-		if (flash_addr_table[index][i] == 0) {
-			continue;
-		}
-
-		/* call flash_get_size() to initialize sector address */
-		size_b[i] =
-		    flash_get_size((vu_long *) flash_addr_table[index][i],
-				   &flash_info[i]);
-		flash_info[i].size = size_b[i];
-		if (flash_info[i].flash_id == FLASH_UNKNOWN) {
-			printf
-			    ("## Unknown FLASH on Bank %d - Size = 0x%08lx = %ld MB\n",
-			     i, size_b[i], size_b[i] << 20);
-			flash_info[i].sector_count = -1;
-			flash_info[i].size = 0;
-		}
-
-		/* Monitor protection ON by default */
-		(void)flash_protect(FLAG_PROTECT_SET, CONFIG_SYS_MONITOR_BASE,
-				    CONFIG_SYS_MONITOR_BASE + CONFIG_SYS_MONITOR_LEN - 1,
-				    &flash_info[i]);
-#ifdef CONFIG_ENV_IS_IN_FLASH
-		(void)flash_protect(FLAG_PROTECT_SET, CONFIG_ENV_ADDR,
-				    CONFIG_ENV_ADDR + CONFIG_ENV_SECT_SIZE - 1,
-				    &flash_info[i]);
-		(void)flash_protect(FLAG_PROTECT_SET, CONFIG_ENV_ADDR_REDUND,
-				    CONFIG_ENV_ADDR_REDUND + CONFIG_ENV_SECT_SIZE - 1,
-				    &flash_info[i]);
-#endif
-
-		total_b += flash_info[i].size;
-	}
-
-	return total_b;
-}
diff --git a/board/amcc/ocotea/init.S b/board/amcc/ocotea/init.S
deleted file mode 100644
index 35085f0..0000000
--- a/board/amcc/ocotea/init.S
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- *  Copyright (C) 2002 Scott McNutt <smcnutt@artesyncp.com>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <ppc_asm.tmpl>
-#include <config.h>
-#include <asm/mmu.h>
-#include <asm/ppc4xx.h>
-
-/**************************************************************************
- * TLB TABLE
- *
- * This table is used by the cpu boot code to setup the initial tlb
- * entries. Rather than make broad assumptions in the cpu source tree,
- * this table lets each board set things up however they like.
- *
- *  Pointer to the table is returned in r1
- *
- *************************************************************************/
-
-	.section .bootpg,"ax"
-	.globl tlbtab
-
-tlbtab:
-	tlbtab_start
-
-	tlbentry(0xf0000000, SZ_256M, 0xf0000000, 1, AC_RWX | SA_IG)
-
-	/*
-	 * TLB entries for SDRAM are not needed on this platform.
-	 * They are dynamically generated in the SPD DDR(2) detection
-	 * routine.
-	 */
-
-	tlbentry(CONFIG_SYS_PERIPHERAL_BASE, SZ_256M, 0x40000000, 1, AC_RW | SA_IG)
-	tlbentry(CONFIG_SYS_ISRAM_BASE, SZ_4K, 0x80000000, 0, AC_RWX)
-	tlbentry(CONFIG_SYS_ISRAM_BASE + 0x1000, SZ_4K, 0x80001000, 0, AC_RWX)
-	tlbentry(CONFIG_SYS_PCI_BASE, SZ_256M, 0x00000000, 2, AC_RW | SA_IG)
-	tlbentry(CONFIG_SYS_PCI_MEMBASE, SZ_256M, 0x00000000, 3, AC_RW | SA_IG)
-	tlbtab_end
diff --git a/board/amcc/ocotea/ocotea.c b/board/amcc/ocotea/ocotea.c
deleted file mode 100644
index 5f11f19..0000000
--- a/board/amcc/ocotea/ocotea.c
+++ /dev/null
@@ -1,387 +0,0 @@
-/*
- *  Copyright (C) 2004 PaulReynolds@lhsolutions.com
- *
- * (C) Copyright 2005
- * Stefan Roese, DENX Software Engineering, sr@denx.de.
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-
-#include <common.h>
-#include "ocotea.h"
-#include <asm/processor.h>
-#include <spd_sdram.h>
-#include <asm/ppc4xx-emac.h>
-
-DECLARE_GLOBAL_DATA_PTR;
-
-#define BOOT_SMALL_FLASH	32	/* 00100000 */
-#define FLASH_ONBD_N		2	/* 00000010 */
-#define FLASH_SRAM_SEL		1	/* 00000001 */
-
-long int fixed_sdram (void);
-void fpga_init (void);
-
-int board_early_init_f (void)
-{
-	unsigned long mfr;
-	unsigned char *fpga_base = (unsigned char *) CONFIG_SYS_FPGA_BASE;
-	unsigned char switch_status;
-	unsigned long cs0_base;
-	unsigned long cs0_size;
-	unsigned long cs0_twt;
-	unsigned long cs2_base;
-	unsigned long cs2_size;
-	unsigned long cs2_twt;
-
-	/*-------------------------------------------------------------------------+
-	  | Initialize EBC CONFIG
-	  +-------------------------------------------------------------------------*/
-	mtebc(EBC0_CFG, EBC_CFG_LE_UNLOCK |
-	      EBC_CFG_PTD_ENABLE | EBC_CFG_RTC_64PERCLK |
-	      EBC_CFG_ATC_PREVIOUS | EBC_CFG_DTC_PREVIOUS |
-	      EBC_CFG_CTC_PREVIOUS | EBC_CFG_EMC_NONDEFAULT |
-	      EBC_CFG_PME_DISABLE | EBC_CFG_PR_32);
-
-	/*-------------------------------------------------------------------------+
-	  | FPGA. Initialize bank 7 with default values.
-	  +-------------------------------------------------------------------------*/
-	mtebc(PB7AP, EBC_BXAP_BME_DISABLED|EBC_BXAP_TWT_ENCODE(7)|
-	      EBC_BXAP_BCE_DISABLE|
-	      EBC_BXAP_CSN_ENCODE(1)|EBC_BXAP_OEN_ENCODE(1)|
-	      EBC_BXAP_WBN_ENCODE(1)|EBC_BXAP_WBF_ENCODE(1)|
-	      EBC_BXAP_TH_ENCODE(1)|EBC_BXAP_RE_DISABLED|
-	      EBC_BXAP_BEM_WRITEONLY|
-	      EBC_BXAP_PEN_DISABLED);
-	mtebc(PB7CR, EBC_BXCR_BAS_ENCODE(0x48300000)|
-	      EBC_BXCR_BS_1MB|EBC_BXCR_BU_RW|EBC_BXCR_BW_8BIT);
-
-	/* read FPGA base register FPGA_REG0 */
-	switch_status = *fpga_base;
-
-	if (switch_status & 0x40) {
-		cs0_base = 0xFFE00000;
-		cs0_size = EBC_BXCR_BS_2MB;
-		cs0_twt = 8;
-		cs2_base = 0xFF800000;
-		cs2_size = EBC_BXCR_BS_4MB;
-		cs2_twt = 10;
-	} else {
-		cs0_base = 0xFFC00000;
-		cs0_size = EBC_BXCR_BS_4MB;
-		cs0_twt = 10;
-		cs2_base = 0xFF800000;
-		cs2_size = EBC_BXCR_BS_2MB;
-		cs2_twt = 8;
-	}
-
-	/*-------------------------------------------------------------------------+
-	  | 1 MB FLASH / 1 MB SRAM. Initialize bank 0 with default values.
-	  +-------------------------------------------------------------------------*/
-	mtebc(PB0AP, EBC_BXAP_BME_DISABLED|EBC_BXAP_TWT_ENCODE(cs0_twt)|
-	      EBC_BXAP_BCE_DISABLE|
-	      EBC_BXAP_CSN_ENCODE(1)|EBC_BXAP_OEN_ENCODE(1)|
-	      EBC_BXAP_WBN_ENCODE(1)|EBC_BXAP_WBF_ENCODE(1)|
-	      EBC_BXAP_TH_ENCODE(1)|EBC_BXAP_RE_DISABLED|
-	      EBC_BXAP_BEM_WRITEONLY|
-	      EBC_BXAP_PEN_DISABLED);
-	mtebc(PB0CR, EBC_BXCR_BAS_ENCODE(cs0_base)|
-	      cs0_size|EBC_BXCR_BU_RW|EBC_BXCR_BW_8BIT);
-
-	/*-------------------------------------------------------------------------+
-	  | 8KB NVRAM/RTC. Initialize bank 1 with default values.
-	  +-------------------------------------------------------------------------*/
-	mtebc(PB1AP, EBC_BXAP_BME_DISABLED|EBC_BXAP_TWT_ENCODE(10)|
-	      EBC_BXAP_BCE_DISABLE|
-	      EBC_BXAP_CSN_ENCODE(1)|EBC_BXAP_OEN_ENCODE(1)|
-	      EBC_BXAP_WBN_ENCODE(1)|EBC_BXAP_WBF_ENCODE(1)|
-	      EBC_BXAP_TH_ENCODE(1)|EBC_BXAP_RE_DISABLED|
-	      EBC_BXAP_BEM_WRITEONLY|
-	      EBC_BXAP_PEN_DISABLED);
-	mtebc(PB1CR, EBC_BXCR_BAS_ENCODE(0x48000000)|
-	      EBC_BXCR_BS_1MB|EBC_BXCR_BU_RW|EBC_BXCR_BW_8BIT);
-
-	/*-------------------------------------------------------------------------+
-	  | 4 MB FLASH. Initialize bank 2 with default values.
-	  +-------------------------------------------------------------------------*/
-	mtebc(PB2AP, EBC_BXAP_BME_DISABLED|EBC_BXAP_TWT_ENCODE(cs2_twt)|
-	      EBC_BXAP_BCE_DISABLE|
-	      EBC_BXAP_CSN_ENCODE(1)|EBC_BXAP_OEN_ENCODE(1)|
-	      EBC_BXAP_WBN_ENCODE(1)|EBC_BXAP_WBF_ENCODE(1)|
-	      EBC_BXAP_TH_ENCODE(1)|EBC_BXAP_RE_DISABLED|
-	      EBC_BXAP_BEM_WRITEONLY|
-	      EBC_BXAP_PEN_DISABLED);
-	mtebc(PB2CR, EBC_BXCR_BAS_ENCODE(cs2_base)|
-	      cs2_size|EBC_BXCR_BU_RW|EBC_BXCR_BW_8BIT);
-
-	/*-------------------------------------------------------------------------+
-	  | FPGA. Initialize bank 7 with default values.
-	  +-------------------------------------------------------------------------*/
-	mtebc(PB7AP, EBC_BXAP_BME_DISABLED|EBC_BXAP_TWT_ENCODE(7)|
-	      EBC_BXAP_BCE_DISABLE|
-	      EBC_BXAP_CSN_ENCODE(1)|EBC_BXAP_OEN_ENCODE(1)|
-	      EBC_BXAP_WBN_ENCODE(1)|EBC_BXAP_WBF_ENCODE(1)|
-	      EBC_BXAP_TH_ENCODE(1)|EBC_BXAP_RE_DISABLED|
-	      EBC_BXAP_BEM_WRITEONLY|
-	      EBC_BXAP_PEN_DISABLED);
-	mtebc(PB7CR, EBC_BXCR_BAS_ENCODE(0x48300000)|
-	      EBC_BXCR_BS_1MB|EBC_BXCR_BU_RW|EBC_BXCR_BW_8BIT);
-
-	/*--------------------------------------------------------------------
-	 * Setup the interrupt controller polarities, triggers, etc.
-	 *-------------------------------------------------------------------*/
-	/*
-	 * Because of the interrupt handling rework to handle 440GX interrupts
-	 * with the common code, we needed to change names of the UIC registers.
-	 * Here the new relationship:
-	 *
-	 * U-Boot name	440GX name
-	 * -----------------------
-	 * UIC0		UICB0
-	 * UIC1		UIC0
-	 * UIC2		UIC1
-	 * UIC3		UIC2
-	 */
-	mtdcr (UIC1SR, 0xffffffff);	/* clear all */
-	mtdcr (UIC1ER, 0x00000000);	/* disable all */
-	mtdcr (UIC1CR, 0x00000009);	/* SMI & UIC1 crit are critical */
-	mtdcr (UIC1PR, 0xfffffe13);	/* per ref-board manual */
-	mtdcr (UIC1TR, 0x01c00008);	/* per ref-board manual */
-	mtdcr (UIC1VR, 0x00000001);	/* int31 highest, base=0x000 */
-	mtdcr (UIC1SR, 0xffffffff);	/* clear all */
-
-	mtdcr (UIC2SR, 0xffffffff);	/* clear all */
-	mtdcr (UIC2ER, 0x00000000);	/* disable all */
-	mtdcr (UIC2CR, 0x00000000);	/* all non-critical */
-	mtdcr (UIC2PR, 0xffffe0ff);	/* per ref-board manual */
-	mtdcr (UIC2TR, 0x00ffc000);	/* per ref-board manual */
-	mtdcr (UIC2VR, 0x00000001);	/* int31 highest, base=0x000 */
-	mtdcr (UIC2SR, 0xffffffff);	/* clear all */
-
-	mtdcr (UIC3SR, 0xffffffff);	/* clear all */
-	mtdcr (UIC3ER, 0x00000000);	/* disable all */
-	mtdcr (UIC3CR, 0x00000000);	/* all non-critical */
-	mtdcr (UIC3PR, 0xffffffff);	/* per ref-board manual */
-	mtdcr (UIC3TR, 0x00ff8c0f);	/* per ref-board manual */
-	mtdcr (UIC3VR, 0x00000001);	/* int31 highest, base=0x000 */
-	mtdcr (UIC3SR, 0xffffffff);	/* clear all */
-
-	mtdcr (UIC0SR, 0xfc000000); /* clear all */
-	mtdcr (UIC0ER, 0x00000000); /* disable all */
-	mtdcr (UIC0CR, 0x00000000); /* all non-critical */
-	mtdcr (UIC0PR, 0xfc000000); /* */
-	mtdcr (UIC0TR, 0x00000000); /* */
-	mtdcr (UIC0VR, 0x00000001); /* */
-	mfsdr (SDR0_MFR, mfr);
-	mfr &= ~SDR0_MFR_ECS_MASK;
-/*	mtsdr(SDR0_MFR, mfr); */
-	fpga_init();
-
-	return 0;
-}
-
-
-int checkboard (void)
-{
-	char buf[64];
-	int i = getenv_f("serial#", buf, sizeof(buf));
-
-	printf ("Board: Ocotea - AMCC PPC440GX Evaluation Board");
-	if (i > 0) {
-		puts(", serial# ");
-		puts(buf);
-	}
-	putc ('\n');
-
-	return (0);
-}
-
-
-phys_size_t initdram (int board_type)
-{
-	long dram_size = 0;
-
-#if defined(CONFIG_SPD_EEPROM)
-	dram_size = spd_sdram ();
-#else
-	dram_size = fixed_sdram ();
-#endif
-	return dram_size;
-}
-
-
-#if !defined(CONFIG_SPD_EEPROM)
-/*************************************************************************
- *  fixed sdram init -- doesn't use serial presence detect.
- *
- *  Assumes:    128 MB, non-ECC, non-registered
- *              PLB @ 133 MHz
- *
- ************************************************************************/
-long int fixed_sdram (void)
-{
-	uint reg;
-
-	/*--------------------------------------------------------------------
-	 * Setup some default
-	 *------------------------------------------------------------------*/
-	mtsdram (SDRAM0_UABBA, 0x00000000);	/* ubba=0 (default)             */
-	mtsdram (SDRAM0_SLIO, 0x00000000);		/* rdre=0 wrre=0 rarw=0         */
-	mtsdram (SDRAM0_DEVOPT, 0x00000000);	/* dll=0 ds=0 (normal)          */
-	mtsdram (SDRAM0_WDDCTR, 0x00000000);	/* wrcp=0 dcd=0                 */
-	mtsdram (SDRAM0_CLKTR, 0x40000000);	/* clkp=1 (90 deg wr) dcdt=0    */
-
-	/*--------------------------------------------------------------------
-	 * Setup for board-specific specific mem
-	 *------------------------------------------------------------------*/
-	/*
-	 * Following for CAS Latency = 2.5 @ 133 MHz PLB
-	 */
-	mtsdram (SDRAM0_B0CR, 0x000a4001);	/* SDBA=0x000 128MB, Mode 3, enabled */
-	mtsdram (SDRAM0_TR0, 0x410a4012);	/* WR=2  WD=1 CL=2.5 PA=3 CP=4 LD=2 */
-	/* RA=10 RD=3                       */
-	mtsdram (SDRAM0_TR1, 0x8080082f);	/* SS=T2 SL=STAGE 3 CD=1 CT=0x02f   */
-	mtsdram (SDRAM0_RTR, 0x08200000);	/* Rate 15.625 ns @ 133 MHz PLB     */
-	mtsdram (SDRAM0_CFG1, 0x00000000);	/* Self-refresh exit, disable PM    */
-	udelay (400);			/* Delay 200 usecs (min)            */
-
-	/*--------------------------------------------------------------------
-	 * Enable the controller, then wait for DCEN to complete
-	 *------------------------------------------------------------------*/
-	mtsdram (SDRAM0_CFG0, 0x86000000);	/* DCEN=1, PMUD=1, 64-bit           */
-	for (;;) {
-		mfsdram (SDRAM0_MCSTS, reg);
-		if (reg & 0x80000000)
-			break;
-	}
-
-	return (128 * 1024 * 1024);	/* 128 MB                           */
-}
-#endif	/* !defined(CONFIG_SPD_EEPROM) */
-
-void fpga_init(void)
-{
-	unsigned long group;
-	unsigned long sdr0_pfc0;
-	unsigned long sdr0_pfc1;
-	unsigned long sdr0_cust0;
-	unsigned long pvr;
-
-	mfsdr (SDR0_PFC0, sdr0_pfc0);
-	mfsdr (SDR0_PFC1, sdr0_pfc1);
-	group = SDR0_PFC1_EPS_DECODE(sdr0_pfc1);
-	pvr = get_pvr ();
-
-	sdr0_pfc0 = (sdr0_pfc0 & ~SDR0_PFC0_GEIE_MASK) | SDR0_PFC0_GEIE_TRE;
-	if ( ((pvr == PVR_440GX_RA) || (pvr == PVR_440GX_RB)) && ((group == 4) || (group == 5))) {
-		sdr0_pfc0 = (sdr0_pfc0 & ~SDR0_PFC0_TRE_MASK) | SDR0_PFC0_TRE_DISABLE;
-		sdr0_pfc1 = (sdr0_pfc1 & ~SDR0_PFC1_CTEMS_MASK) | SDR0_PFC1_CTEMS_EMS;
-		out8(FPGA_REG2, (in8(FPGA_REG2) & ~FPGA_REG2_EXT_INTFACE_MASK) |
-		     FPGA_REG2_EXT_INTFACE_ENABLE);
-		mtsdr (SDR0_PFC0, sdr0_pfc0);
-		mtsdr (SDR0_PFC1, sdr0_pfc1);
-	} else {
-		sdr0_pfc0 = (sdr0_pfc0 & ~SDR0_PFC0_TRE_MASK) | SDR0_PFC0_TRE_ENABLE;
-		switch (group)
-		{
-		case 0:
-		case 1:
-		case 2:
-			/* CPU trace A */
-			out8(FPGA_REG2, (in8(FPGA_REG2) & ~FPGA_REG2_EXT_INTFACE_MASK) |
-			     FPGA_REG2_EXT_INTFACE_ENABLE);
-			sdr0_pfc1 = (sdr0_pfc1 & ~SDR0_PFC1_CTEMS_MASK) | SDR0_PFC1_CTEMS_EMS;
-			mtsdr (SDR0_PFC0, sdr0_pfc0);
-			mtsdr (SDR0_PFC1, sdr0_pfc1);
-			break;
-		case 3:
-		case 4:
-		case 5:
-		case 6:
-			/* CPU trace B - Over EBMI */
-			sdr0_pfc1 = (sdr0_pfc1 & ~SDR0_PFC1_CTEMS_MASK) | SDR0_PFC1_CTEMS_CPUTRACE;
-			mtsdr (SDR0_PFC0, sdr0_pfc0);
-			mtsdr (SDR0_PFC1, sdr0_pfc1);
-			out8(FPGA_REG2, (in8(FPGA_REG2) & ~FPGA_REG2_EXT_INTFACE_MASK) |
-			     FPGA_REG2_EXT_INTFACE_DISABLE);
-			break;
-		}
-	}
-
-	/* Initialize the ethernet specific functions in the fpga */
-	mfsdr(SDR0_PFC1, sdr0_pfc1);
-	mfsdr(SDR0_CUST0, sdr0_cust0);
-	if ( (SDR0_PFC1_EPS_DECODE(sdr0_pfc1) == 4) &&
-	    ((SDR0_CUST0_RGMII2_DECODE(sdr0_cust0) == RGMII_FER_GMII) ||
-	     (SDR0_CUST0_RGMII2_DECODE(sdr0_cust0) == RGMII_FER_TBI)))
-	{
-		if ((in8(FPGA_REG0) & FPGA_REG0_ECLS_MASK) == FPGA_REG0_ECLS_VER1)
-		{
-			out8(FPGA_REG3, (in8(FPGA_REG3) & ~FPGA_REG3_ENET_MASK1) |
-			     FPGA_REG3_ENET_GROUP7);
-		}
-		else
-		{
-			if (SDR0_CUST0_RGMII2_DECODE(sdr0_cust0) == RGMII_FER_GMII)
-			{
-				out8(FPGA_REG3, (in8(FPGA_REG3) & ~FPGA_REG3_ENET_MASK2) |
-				     FPGA_REG3_ENET_GROUP7);
-			}
-			else
-			{
-				out8(FPGA_REG3, (in8(FPGA_REG3) & ~FPGA_REG3_ENET_MASK2) |
-				     FPGA_REG3_ENET_GROUP8);
-			}
-		}
-	}
-	else
-	{
-		if ((in8(FPGA_REG0) & FPGA_REG0_ECLS_MASK) == FPGA_REG0_ECLS_VER1)
-		{
-			out8(FPGA_REG3, (in8(FPGA_REG3) & ~FPGA_REG3_ENET_MASK1) |
-			     FPGA_REG3_ENET_ENCODE1(SDR0_PFC1_EPS_DECODE(sdr0_pfc1)));
-		}
-		else
-		{
-			out8(FPGA_REG3, (in8(FPGA_REG3) & ~FPGA_REG3_ENET_MASK2) |
-			     FPGA_REG3_ENET_ENCODE2(SDR0_PFC1_EPS_DECODE(sdr0_pfc1)));
-		}
-	}
-	out8(FPGA_REG4, FPGA_REG4_GPHY_MODE10 |
-	     FPGA_REG4_GPHY_MODE100 | FPGA_REG4_GPHY_MODE1000 |
-	     FPGA_REG4_GPHY_FRC_DPLX | FPGA_REG4_CONNECT_PHYS);
-
-	/* reset the gigabyte phy if necessary */
-	if (SDR0_PFC1_EPS_DECODE(sdr0_pfc1) >= 3)
-	{
-		if ((in8(FPGA_REG0) & FPGA_REG0_ECLS_MASK) == FPGA_REG0_ECLS_VER1)
-		{
-			out8(FPGA_REG3, in8(FPGA_REG3) & ~FPGA_REG3_GIGABIT_RESET_DISABLE);
-			udelay(10000);
-			out8(FPGA_REG3, in8(FPGA_REG3) | FPGA_REG3_GIGABIT_RESET_DISABLE);
-		}
-		else
-		{
-			out8(FPGA_REG2, in8(FPGA_REG2) & ~FPGA_REG2_GIGABIT_RESET_DISABLE);
-			udelay(10000);
-			out8(FPGA_REG2, in8(FPGA_REG2) | FPGA_REG2_GIGABIT_RESET_DISABLE);
-		}
-	}
-
-	/*
-	 * new Ocotea with Rev. F (pass 3) chips has SMII PHY reset
-	 */
-	if ((in8(FPGA_REG0) & FPGA_REG0_ECLS_MASK) == FPGA_REG0_ECLS_VER2) {
-		out8(FPGA_REG2, in8(FPGA_REG2) & ~FPGA_REG2_SMII_RESET_DISABLE);
-		udelay(10000);
-		out8(FPGA_REG2, in8(FPGA_REG2) | FPGA_REG2_SMII_RESET_DISABLE);
-	}
-
-	/* Turn off the LED's */
-	out8(FPGA_REG3, (in8(FPGA_REG3) & ~FPGA_REG3_STAT_MASK) |
-	     FPGA_REG3_STAT_LED8_DISAB | FPGA_REG3_STAT_LED4_DISAB |
-	     FPGA_REG3_STAT_LED2_DISAB | FPGA_REG3_STAT_LED1_DISAB);
-
-	return;
-}
diff --git a/board/amcc/ocotea/ocotea.h b/board/amcc/ocotea/ocotea.h
deleted file mode 100644
index 853002f..0000000
--- a/board/amcc/ocotea/ocotea.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * (C) Copyright 2004
- * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-/* Board specific FPGA stuff ... */
-#define FPGA_REG0                       (CONFIG_SYS_FPGA_BASE + 0x00)
-#define   FPGA_REG0_SSCG_MASK             0x80
-#define   FPGA_REG0_SSCG_DISABLE          0x00
-#define   FPGA_REG0_SSCG_ENABLE           0x80
-#define   FPGA_REG0_BOOT_MASK             0x40
-#define   FPGA_REG0_BOOT_LARGE_FLASH      0x00
-#define   FPGA_REG0_BOOT_SMALL_FLASH      0x40
-#define   FPGA_REG0_ECLS_MASK             0x38  /* New for Ocotea Rev 2 */
-#define   FPGA_REG0_ECLS_0                0x20  /* New for Ocotea Rev 2 */
-#define   FPGA_REG0_ECLS_1                0x10  /* New for Ocotea Rev 2 */
-#define   FPGA_REG0_ECLS_2                0x08  /* New for Ocotea Rev 2 */
-#define   FPGA_REG0_ECLS_VER1             0x00  /* New for Ocotea Rev 2 */
-#define   FPGA_REG0_ECLS_VER3             0x08  /* New for Ocotea Rev 2 */
-#define   FPGA_REG0_ECLS_VER4             0x10  /* New for Ocotea Rev 2 */
-#define   FPGA_REG0_ECLS_VER5             0x18  /* New for Ocotea Rev 2 */
-#define   FPGA_REG0_ECLS_VER2             0x20  /* New for Ocotea Rev 2 */
-#define   FPGA_REG0_ECLS_VER6             0x28  /* New for Ocotea Rev 2 */
-#define   FPGA_REG0_ECLS_VER7             0x30  /* New for Ocotea Rev 2 */
-#define   FPGA_REG0_ECLS_VER8             0x38  /* New for Ocotea Rev 2 */
-#define   FPGA_REG0_ARBITER_MASK          0x04
-#define   FPGA_REG0_ARBITER_EXT           0x00
-#define   FPGA_REG0_ARBITER_INT           0x04
-#define   FPGA_REG0_ONBOARD_FLASH_MASK    0x02
-#define   FPGA_REG0_ONBOARD_FLASH_ENABLE  0x00
-#define   FPGA_REG0_ONBOARD_FLASH_DISABLE 0x02
-#define   FPGA_REG0_FLASH                 0x01
-#define FPGA_REG1                       (CONFIG_SYS_FPGA_BASE + 0x01)
-#define   FPGA_REG1_9772_FSELFBX_MASK     0x80
-#define   FPGA_REG1_9772_FSELFBX_6        0x00
-#define   FPGA_REG1_9772_FSELFBX_10       0x80
-#define   FPGA_REG1_9531_SX_MASK          0x60
-#define   FPGA_REG1_9531_SX_33MHZ         0x00
-#define   FPGA_REG1_9531_SX_100MHZ        0x20
-#define   FPGA_REG1_9531_SX_66MHZ         0x40
-#define   FPGA_REG1_9531_SX_133MHZ        0x60
-#define   FPGA_REG1_9772_FSELBX_MASK      0x18
-#define   FPGA_REG1_9772_FSELBX_4         0x00
-#define   FPGA_REG1_9772_FSELBX_6         0x08
-#define   FPGA_REG1_9772_FSELBX_8         0x10
-#define   FPGA_REG1_9772_FSELBX_10        0x18
-#define   FPGA_REG1_SOURCE_MASK           0x07
-#define   FPGA_REG1_SOURCE_TC             0x00
-#define   FPGA_REG1_SOURCE_66MHZ          0x01
-#define   FPGA_REG1_SOURCE_50MHZ          0x02
-#define   FPGA_REG1_SOURCE_33MHZ          0x03
-#define   FPGA_REG1_SOURCE_25MHZ          0x04
-#define   FPGA_REG1_SOURCE_SSDIV1         0x05
-#define   FPGA_REG1_SOURCE_SSDIV2         0x06
-#define   FPGA_REG1_SOURCE_SSDIV4         0x07
-#define FPGA_REG2                       (CONFIG_SYS_FPGA_BASE + 0x02)
-#define   FPGA_REG2_TC0                   0x80
-#define   FPGA_REG2_TC1                   0x40
-#define   FPGA_REG2_TC2                   0x20
-#define   FPGA_REG2_TC3                   0x10
-#define   FPGA_REG2_GIGABIT_RESET_DISABLE 0x08   /*Use on Ocotea pass 2 boards*/
-#define   FPGA_REG2_EXT_INTFACE_MASK      0x04
-#define   FPGA_REG2_EXT_INTFACE_ENABLE    0x00
-#define   FPGA_REG2_EXT_INTFACE_DISABLE   0x04
-#define   FPGA_REG2_SMII_RESET_DISABLE    0x02   /*Use on Ocotea pass 3 boards*/
-#define   FPGA_REG2_DEFAULT_UART1_N       0x01
-#define FPGA_REG3                       (CONFIG_SYS_FPGA_BASE + 0x03)
-#define   FPGA_REG3_GIGABIT_RESET_DISABLE 0x80   /*Use on Ocotea pass 1 boards*/
-#define   FPGA_REG3_ENET_MASK1            0x70   /*Use on Ocotea pass 1 boards*/
-#define   FPGA_REG3_ENET_MASK2            0xF0   /*Use on Ocotea pass 2 boards*/
-#define   FPGA_REG3_ENET_GROUP0           0x00
-#define   FPGA_REG3_ENET_GROUP1           0x10
-#define   FPGA_REG3_ENET_GROUP2           0x20
-#define   FPGA_REG3_ENET_GROUP3           0x30
-#define   FPGA_REG3_ENET_GROUP4           0x40
-#define   FPGA_REG3_ENET_GROUP5           0x50
-#define   FPGA_REG3_ENET_GROUP6           0x60
-#define   FPGA_REG3_ENET_GROUP7           0x70
-#define   FPGA_REG3_ENET_GROUP8           0x80   /*Use on Ocotea pass 2 boards*/
-#define   FPGA_REG3_ENET_ENCODE1(n) ((((unsigned long)(n))&0x07)<<4) /*pass1*/
-#define   FPGA_REG3_ENET_DECODE1(n) ((((unsigned long)(n))>>4)&0x07) /*pass1*/
-#define   FPGA_REG3_ENET_ENCODE2(n) ((((unsigned long)(n))&0x0F)<<4) /*pass2*/
-#define   FPGA_REG3_ENET_DECODE2(n) ((((unsigned long)(n))>>4)&0x0F) /*pass2*/
-#define   FPGA_REG3_STAT_MASK             0x0F
-#define   FPGA_REG3_STAT_LED8_ENAB        0x08
-#define   FPGA_REG3_STAT_LED4_ENAB        0x04
-#define   FPGA_REG3_STAT_LED2_ENAB        0x02
-#define   FPGA_REG3_STAT_LED1_ENAB        0x01
-#define   FPGA_REG3_STAT_LED8_DISAB       0x00
-#define   FPGA_REG3_STAT_LED4_DISAB       0x00
-#define   FPGA_REG3_STAT_LED2_DISAB       0x00
-#define   FPGA_REG3_STAT_LED1_DISAB       0x00
-#define FPGA_REG4                       (CONFIG_SYS_FPGA_BASE + 0x04)
-#define   FPGA_REG4_GPHY_MODE10           0x80
-#define   FPGA_REG4_GPHY_MODE100          0x40
-#define   FPGA_REG4_GPHY_MODE1000         0x20
-#define   FPGA_REG4_GPHY_FRC_DPLX         0x10
-#define   FPGA_REG4_GPHY_ANEG_DIS         0x08
-#define   FPGA_REG4_CONNECT_PHYS          0x04
-
-
-#define   SDR0_CUST0_ENET3_MASK         0x00000080
-#define   SDR0_CUST0_ENET3_COPPER       0x00000000
-#define   SDR0_CUST0_ENET3_FIBER        0x00000080
-#define   SDR0_CUST0_RGMII3_MASK        0x00000070
-#define   SDR0_CUST0_RGMII3_ENCODE(n) ((((unsigned long)(n))&0x7)<<4)
-#define   SDR0_CUST0_RGMII3_DECODE(n) ((((unsigned long)(n))>>4)&0x07)
-#define   SDR0_CUST0_RGMII3_DISAB       0x00000000
-#define   SDR0_CUST0_RGMII3_RTBI        0x00000040
-#define   SDR0_CUST0_RGMII3_RGMII       0x00000050
-#define   SDR0_CUST0_RGMII3_TBI         0x00000060
-#define   SDR0_CUST0_RGMII3_GMII        0x00000070
-#define   SDR0_CUST0_ENET2_MASK         0x00000008
-#define   SDR0_CUST0_ENET2_COPPER       0x00000000
-#define   SDR0_CUST0_ENET2_FIBER        0x00000008
-#define   SDR0_CUST0_RGMII2_MASK        0x00000007
-#define   SDR0_CUST0_RGMII2_ENCODE(n) ((((unsigned long)(n))&0x7)<<0)
-#define   SDR0_CUST0_RGMII2_DECODE(n) ((((unsigned long)(n))>>0)&0x07)
-#define   SDR0_CUST0_RGMII2_DISAB       0x00000000
-#define   SDR0_CUST0_RGMII2_RTBI        0x00000004
-#define   SDR0_CUST0_RGMII2_RGMII       0x00000005
-#define   SDR0_CUST0_RGMII2_TBI         0x00000006
-#define   SDR0_CUST0_RGMII2_GMII        0x00000007
diff --git a/board/amcc/taihu/Kconfig b/board/amcc/taihu/Kconfig
deleted file mode 100644
index faafb08..0000000
--- a/board/amcc/taihu/Kconfig
+++ /dev/null
@@ -1,16 +0,0 @@
-if TARGET_TAIHU
-
-config SYS_BOARD
-	default "taihu"
-
-config SYS_VENDOR
-	default "amcc"
-
-config SYS_CONFIG_NAME
-	default "taihu"
-
-config DISPLAY_BOARDINFO
-	bool
-	default y
-
-endif
diff --git a/board/amcc/taihu/MAINTAINERS b/board/amcc/taihu/MAINTAINERS
deleted file mode 100644
index 2efc254..0000000
--- a/board/amcc/taihu/MAINTAINERS
+++ /dev/null
@@ -1,6 +0,0 @@
-TAIHU BOARD
-M:	John Otken <jotken@softadvances.com>
-S:	Maintained
-F:	board/amcc/taihu/
-F:	include/configs/taihu.h
-F:	configs/taihu_defconfig
diff --git a/board/amcc/taihu/Makefile b/board/amcc/taihu/Makefile
deleted file mode 100644
index 65606fe..0000000
--- a/board/amcc/taihu/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-# (C) Copyright 2000-2006
-# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
-#
-# SPDX-License-Identifier:	GPL-2.0+
-#
-
-obj-y	= taihu.o flash.o lcd.o update.o
diff --git a/board/amcc/taihu/flash.c b/board/amcc/taihu/flash.c
deleted file mode 100644
index 0780488..0000000
--- a/board/amcc/taihu/flash.c
+++ /dev/null
@@ -1,1063 +0,0 @@
-/*
- * (C) Copyright 2000
- * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-/*
- * Modified 4/5/2001
- * Wait for completion of each sector erase command issued
- * 4/5/2001
- * Chris Hallinan - DS4.COM, Inc. - clh@net1plus.com
- */
-
-#include <common.h>
-#include <asm/ppc4xx.h>
-#include <asm/processor.h>
-
-flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];	/* info for FLASH chips        */
-
-#undef DEBUG
-#ifdef DEBUG
-#define DEBUGF(x...) printf(x)
-#else
-#define DEBUGF(x...)
-#endif				/* DEBUG */
-
-#define CONFIG_SYS_FLASH_CHAR_SIZE unsigned char
-#define CONFIG_SYS_FLASH_CHAR_ADDR0 (0x0aaa)
-#define CONFIG_SYS_FLASH_CHAR_ADDR1 (0x0555)
-/*-----------------------------------------------------------------------
- * Functions
- */
-static ulong flash_get_size(vu_long * addr, flash_info_t * info);
-static void flash_get_offsets(ulong base, flash_info_t * info);
-static int write_word(flash_info_t * info, ulong dest, ulong data);
-#ifdef FLASH_BASE1_PRELIM
-static int write_word_1(flash_info_t * info, ulong dest, ulong data);
-static int write_word_2(flash_info_t * info, ulong dest, ulong data);
-static int flash_erase_1(flash_info_t * info, int s_first, int s_last);
-static int flash_erase_2(flash_info_t * info, int s_first, int s_last);
-static ulong flash_get_size_1(vu_long * addr, flash_info_t * info);
-static ulong flash_get_size_2(vu_long * addr, flash_info_t * info);
-#endif
-
-unsigned long flash_init(void)
-{
-	unsigned long size_b0, size_b1=0;
-	int i;
-
-	/* Init: no FLASHes known */
-	for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
-		flash_info[i].flash_id = FLASH_UNKNOWN;
-	}
-
-	/* Static FLASH Bank configuration here - FIXME XXX */
-
-	size_b0 =
-	    flash_get_size((vu_long *) FLASH_BASE0_PRELIM, &flash_info[0]);
-
-	if (flash_info[0].flash_id == FLASH_UNKNOWN) {
-		printf("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
-		       size_b0, size_b0 << 20);
-	}
-
-	if (size_b0) {
-		/* Setup offsets */
-		flash_get_offsets(FLASH_BASE0_PRELIM, &flash_info[0]);
-		/* Monitor protection ON by default */
-		(void)flash_protect(FLAG_PROTECT_SET,
-				    CONFIG_SYS_MONITOR_BASE,
-				    CONFIG_SYS_MONITOR_BASE + CONFIG_SYS_MONITOR_LEN - 1,
-				    &flash_info[0]);
-#ifdef CONFIG_ENV_IS_IN_FLASH
-		(void)flash_protect(FLAG_PROTECT_SET, CONFIG_ENV_ADDR,
-				    CONFIG_ENV_ADDR + CONFIG_ENV_SECT_SIZE - 1,
-				    &flash_info[0]);
-		(void)flash_protect(FLAG_PROTECT_SET, CONFIG_ENV_ADDR_REDUND,
-				    CONFIG_ENV_ADDR_REDUND + CONFIG_ENV_SECT_SIZE - 1,
-				    &flash_info[0]);
-#endif
-		/* Also protect sector containing initial power-up instruction */
-		/* (flash_protect() checks address range - other call ignored) */
-		(void)flash_protect(FLAG_PROTECT_SET,
-				    0xFFFFFFFC, 0xFFFFFFFF, &flash_info[0]);
-
-		flash_info[0].size = size_b0;
-	}
-#ifdef FLASH_BASE1_PRELIM
-	size_b1 =
-	    flash_get_size((vu_long *) FLASH_BASE1_PRELIM, &flash_info[1])*2;
-
-	if (flash_info[1].flash_id == FLASH_UNKNOWN) {
-		printf("## Unknown FLASH on Bank 1 - Size = 0x%08lx = %ld MB\n",
-		       size_b1, size_b1 << 20);
-	}
-
-	if (size_b1) {
-		/* Setup offsets */
-		flash_get_offsets(FLASH_BASE1_PRELIM, &flash_info[1]);
-		flash_info[1].size = size_b1;
-	}
-#endif
-	return (size_b0 + size_b1);
-}
-
-static void flash_get_offsets(ulong base, flash_info_t * info)
-{
-	int i;
-
-	/* set up sector start address table */
-	if (((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) ||
-	    (info->flash_id == FLASH_AM040)) {
-		for (i = 0; i < info->sector_count; i++)
-			info->start[i] = base + (i * 0x00010000);
-	} else if ((info->flash_id & FLASH_TYPEMASK) == FLASH_AMLV128U) {
-		for (i = 0; i < info->sector_count; i++) {
-			info->start[i] = base + (i * 0x00010000*2);
-		}
-	} else if ((info->flash_id & FLASH_TYPEMASK) == FLASH_S29GL128N ) {
-		for (i = 0; i < info->sector_count; i++) {
-			info->start[i] = base + (i * 0x00020000*2);
-		}
-	} else {
-		if (info->flash_id & FLASH_BTYPE) {
-			/* set sector offsets for bottom boot block type        */
-			info->start[0] = base + 0x00000000;
-			info->start[1] = base + 0x00004000;
-			info->start[2] = base + 0x00006000;
-			info->start[3] = base + 0x00008000;
-			for (i = 4; i < info->sector_count; i++) {
-				info->start[i] =
-				    base + (i * 0x00010000) - 0x00030000;
-			}
-		} else {
-			/* set sector offsets for top boot block type           */
-			i = info->sector_count - 1;
-			info->start[i--] = base + info->size - 0x00004000;
-			info->start[i--] = base + info->size - 0x00006000;
-			info->start[i--] = base + info->size - 0x00008000;
-			for (; i >= 0; i--) {
-				info->start[i] = base + i * 0x00010000;
-			}
-		}
-	}
-}
-
-
-void flash_print_info(flash_info_t * info)
-{
-	int i;
-	int k;
-	int size;
-	int erased;
-	volatile unsigned long *flash;
-
-	if (info->flash_id == FLASH_UNKNOWN) {
-		printf("missing or unknown FLASH type\n");
-		return;
-	}
-
-	switch (info->flash_id & FLASH_VENDMASK) {
-	case FLASH_MAN_AMD:
-		printf("AMD ");
-		break;
-	case FLASH_MAN_STM:
-		printf("STM ");
-		break;
-	case FLASH_MAN_FUJ:
-		printf("FUJITSU ");
-		break;
-	case FLASH_MAN_SST:
-		printf("SST ");
-		break;
-	default:
-		printf("Unknown Vendor ");
-		break;
-	}
-
-	switch (info->flash_id & FLASH_TYPEMASK) {
-	case FLASH_AM040:
-		printf("AM29F040 (512 Kbit, uniform sector size)\n");
-		break;
-	case FLASH_AM400B:
-		printf("AM29LV400B (4 Mbit, bottom boot sect)\n");
-		break;
-	case FLASH_AM400T:
-		printf("AM29LV400T (4 Mbit, top boot sector)\n");
-		break;
-	case FLASH_AM800B:
-		printf("AM29LV800B (8 Mbit, bottom boot sect)\n");
-		break;
-	case FLASH_AM800T:
-		printf("AM29LV800T (8 Mbit, top boot sector)\n");
-		break;
-	case FLASH_AMD016:
-		printf("AM29F016D (16 Mbit, uniform sector size)\n");
-		break;
-	case FLASH_AM160B:
-		printf("AM29LV160B (16 Mbit, bottom boot sect)\n");
-		break;
-	case FLASH_AM160T:
-		printf("AM29LV160T (16 Mbit, top boot sector)\n");
-		break;
-	case FLASH_AM320B:
-		printf("AM29LV320B (32 Mbit, bottom boot sect)\n");
-		break;
-	case FLASH_AM320T:
-		printf("AM29LV320T (32 Mbit, top boot sector)\n");
-		break;
-	case FLASH_AM033C:
-		printf("AM29LV033C (32 Mbit, top boot sector)\n");
-		break;
-	case FLASH_AMLV128U:
-		printf("AM29LV128U (128 Mbit * 2, top boot sector)\n");
-		break;
-	case FLASH_SST800A:
-		printf("SST39LF/VF800 (8 Mbit, uniform sector size)\n");
-		break;
-	case FLASH_SST160A:
-		printf("SST39LF/VF160 (16 Mbit, uniform sector size)\n");
-		break;
-	case FLASH_STMW320DT:
-		printf ("M29W320DT (32 M, top sector)\n");
-		break;
-	case FLASH_S29GL128N:
-		printf ("S29GL128N (256 Mbit, uniform sector size)\n");
-		break;
-	default:
-		printf("Unknown Chip Type\n");
-		break;
-	}
-
-	printf("  Size: %ld KB in %d Sectors\n",
-	       info->size >> 10, info->sector_count);
-
-	printf("  Sector Start Addresses:");
-	for (i = 0; i < info->sector_count; ++i) {
-		/*
-		 * Check if whole sector is erased
-		 */
-		if (i != (info->sector_count - 1))
-			size = info->start[i + 1] - info->start[i];
-		else
-			size = info->start[0] + info->size - info->start[i];
-		erased = 1;
-		flash = (volatile unsigned long *)info->start[i];
-		size = size >> 2;	/* divide by 4 for longword access */
-		for (k = 0; k < size; k++) {
-			if (*flash++ != 0xffffffff) {
-				erased = 0;
-				break;
-			}
-		}
-
-		if ((i % 5) == 0)
-			printf("\n   ");
-		printf(" %08lX%s%s",
-		       info->start[i],
-		       erased ? " E" : "  ", info->protect[i] ? "RO " : "   ");
-	}
-	printf("\n");
-	return;
-}
-
-
-/*
- * The following code cannot be run from FLASH!
- */
-#ifdef FLASH_BASE1_PRELIM
-static ulong flash_get_size(vu_long * addr, flash_info_t * info)
-{
-	if ((ulong)addr == FLASH_BASE1_PRELIM) {
-		return flash_get_size_2(addr, info);
-	} else {
-		return flash_get_size_1(addr, info);
-	}
-}
-
-static ulong flash_get_size_1(vu_long * addr, flash_info_t * info)
-#else
-static ulong flash_get_size(vu_long * addr, flash_info_t * info)
-#endif
-{
-	short i;
-	CONFIG_SYS_FLASH_WORD_SIZE value;
-	ulong base = (ulong) addr;
-	volatile CONFIG_SYS_FLASH_WORD_SIZE *addr2 = (CONFIG_SYS_FLASH_WORD_SIZE *) addr;
-
-	DEBUGF("FLASH ADDR: %08x\n", (unsigned)addr);
-
-	/* Write auto select command: read Manufacturer ID */
-	addr2[CONFIG_SYS_FLASH_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00AA00AA;
-	addr2[CONFIG_SYS_FLASH_ADDR1] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00550055;
-	addr2[CONFIG_SYS_FLASH_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00900090;
-	udelay(1000);
-
-	value = addr2[0];
-	DEBUGF("FLASH MANUFACT: %x\n", value);
-
-	switch (value) {
-	case (CONFIG_SYS_FLASH_WORD_SIZE) AMD_MANUFACT:
-		info->flash_id = FLASH_MAN_AMD;
-		break;
-	case (CONFIG_SYS_FLASH_WORD_SIZE) FUJ_MANUFACT:
-		info->flash_id = FLASH_MAN_FUJ;
-		break;
-	case (CONFIG_SYS_FLASH_WORD_SIZE) SST_MANUFACT:
-		info->flash_id = FLASH_MAN_SST;
-		break;
-	case (CONFIG_SYS_FLASH_WORD_SIZE) STM_MANUFACT:
-		info->flash_id = FLASH_MAN_STM;
-		break;
-	default:
-		info->flash_id = FLASH_UNKNOWN;
-		info->sector_count = 0;
-		info->size = 0;
-		return 0;	/* no or unknown flash  */
-	}
-
-	value = addr2[1];	/* device ID            */
-	DEBUGF("\nFLASH DEVICEID: %x\n", value);
-
-	switch (value) {
-	case (CONFIG_SYS_FLASH_WORD_SIZE) AMD_ID_LV040B:
-		info->flash_id += FLASH_AM040;
-		info->sector_count = 8;
-		info->size = 0x0080000;	/* => 512 ko */
-		break;
-
-	case (CONFIG_SYS_FLASH_WORD_SIZE) AMD_ID_F040B:
-		info->flash_id += FLASH_AM040;
-		info->sector_count = 8;
-		info->size = 0x0080000;	/* => 512 ko */
-		break;
-
-	case (CONFIG_SYS_FLASH_WORD_SIZE) STM_ID_M29W040B:
-		info->flash_id += FLASH_AM040;
-		info->sector_count = 8;
-		info->size = 0x0080000;	/* => 512 ko */
-		break;
-
-	case (CONFIG_SYS_FLASH_WORD_SIZE) AMD_ID_F016D:
-		info->flash_id += FLASH_AMD016;
-		info->sector_count = 32;
-		info->size = 0x00200000;
-		break;		/* => 2 MB              */
-
-	case (CONFIG_SYS_FLASH_WORD_SIZE) AMD_ID_LV033C:
-		info->flash_id += FLASH_AMDLV033C;
-		info->sector_count = 64;
-		info->size = 0x00400000;
-		break;		/* => 4 MB              */
-
-	case (CONFIG_SYS_FLASH_WORD_SIZE) AMD_ID_LV400T:
-		info->flash_id += FLASH_AM400T;
-		info->sector_count = 11;
-		info->size = 0x00080000;
-		break;		/* => 0.5 MB            */
-
-	case (CONFIG_SYS_FLASH_WORD_SIZE) AMD_ID_LV400B:
-		info->flash_id += FLASH_AM400B;
-		info->sector_count = 11;
-		info->size = 0x00080000;
-		break;		/* => 0.5 MB            */
-
-	case (CONFIG_SYS_FLASH_WORD_SIZE) AMD_ID_LV800T:
-		info->flash_id += FLASH_AM800T;
-		info->sector_count = 19;
-		info->size = 0x00100000;
-		break;		/* => 1 MB              */
-
-	case (CONFIG_SYS_FLASH_WORD_SIZE) AMD_ID_LV800B:
-		info->flash_id += FLASH_AM800B;
-		info->sector_count = 19;
-		info->size = 0x00100000;
-		break;		/* => 1 MB              */
-
-	case (CONFIG_SYS_FLASH_WORD_SIZE) AMD_ID_LV160T:
-		info->flash_id += FLASH_AM160T;
-		info->sector_count = 35;
-		info->size = 0x00200000;
-		break;		/* => 2 MB              */
-
-	case (CONFIG_SYS_FLASH_WORD_SIZE) AMD_ID_LV160B:
-		info->flash_id += FLASH_AM160B;
-		info->sector_count = 35;
-		info->size = 0x00200000;
-		break;		/* => 2 MB              */
-	default:
-		info->flash_id = FLASH_UNKNOWN;
-		return 0;	/* => no or unknown flash */
-	}
-
-	/* set up sector start address table */
-	if (((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) ||
-	    ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM040) ||
-	    ((info->flash_id & FLASH_TYPEMASK) == FLASH_AMD016)) {
-		for (i = 0; i < info->sector_count; i++)
-			info->start[i] = base + (i * 0x00010000);
-	}
-	else if ((info->flash_id & FLASH_TYPEMASK) == FLASH_AMLV128U) {
-		for (i = 0; i < info->sector_count; i++)
-			info->start[i] = base + (i * 0x00010000 * 2);
-	} else {
-		if (info->flash_id & FLASH_BTYPE) {
-			/* set sector offsets for bottom boot block type        */
-			info->start[0] = base + 0x00000000;
-			info->start[1] = base + 0x00004000;
-			info->start[2] = base + 0x00006000;
-			info->start[3] = base + 0x00008000;
-			for (i = 4; i < info->sector_count; i++) {
-				info->start[i] =
-				    base + (i * 0x00010000) - 0x00030000;
-			}
-		} else {
-			/* set sector offsets for top boot block type           */
-			i = info->sector_count - 1;
-			info->start[i--] = base + info->size - 0x00004000;
-			info->start[i--] = base + info->size - 0x00006000;
-			info->start[i--] = base + info->size - 0x00008000;
-			for (; i >= 0; i--) {
-				info->start[i] = base + i * 0x00010000;
-			}
-		}
-	}
-
-	/* check for protected sectors */
-	for (i = 0; i < info->sector_count; i++) {
-		/* read sector protection at sector address, (A7 .. A0) = 0x02 */
-		/* D0 = 1 if protected */
-		addr2 = (volatile CONFIG_SYS_FLASH_WORD_SIZE *)(info->start[i]);
-
-		/* For AMD29033C flash we need to resend the command of *
-		 * reading flash protection for upper 8 Mb of flash     */
-		if (i == 32) {
-			addr2[CONFIG_SYS_FLASH_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0xAAAAAAAA;
-			addr2[CONFIG_SYS_FLASH_ADDR1] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x55555555;
-			addr2[CONFIG_SYS_FLASH_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x90909090;
-		}
-
-		if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST)
-			info->protect[i] = 0;
-		else
-			info->protect[i] = addr2[2] & 1;
-	}
-
-	/* issue bank reset to return to read mode */
-	addr2[0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00F000F0;
-
-	return info->size;
-}
-
-static int wait_for_DQ7_1(flash_info_t * info, int sect)
-{
-	ulong start, now, last;
-	volatile CONFIG_SYS_FLASH_WORD_SIZE *addr =
-	    (CONFIG_SYS_FLASH_WORD_SIZE *) (info->start[sect]);
-
-	start = get_timer(0);
-	last = start;
-	while ((addr[0] & (CONFIG_SYS_FLASH_WORD_SIZE) 0x00800080) !=
-	       (CONFIG_SYS_FLASH_WORD_SIZE) 0x00800080) {
-		if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
-			printf("Timeout\n");
-			return -1;
-		}
-		/* show that we're waiting */
-		if ((now - last) > 1000) {	/* every second */
-			putc('.');
-			last = now;
-		}
-	}
-	return 0;
-}
-
-#ifdef FLASH_BASE1_PRELIM
-int flash_erase(flash_info_t * info, int s_first, int s_last)
-{
-	if (((info->flash_id & FLASH_TYPEMASK) == FLASH_AM320B) ||
-	    ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM320T) ||
-	    ((info->flash_id & FLASH_TYPEMASK) == FLASH_AMLV128U) ||
-	    ((info->flash_id & FLASH_TYPEMASK) == FLASH_S29GL128N) ||
-	    ((info->flash_id & FLASH_TYPEMASK) == FLASH_STMW320DT)) {
-		return flash_erase_2(info, s_first, s_last);
-	} else {
-		return flash_erase_1(info, s_first, s_last);
-	}
-}
-
-static int flash_erase_1(flash_info_t * info, int s_first, int s_last)
-#else
-int flash_erase(flash_info_t * info, int s_first, int s_last)
-#endif
-{
-	volatile CONFIG_SYS_FLASH_WORD_SIZE *addr = (CONFIG_SYS_FLASH_WORD_SIZE *) (info->start[0]);
-	volatile CONFIG_SYS_FLASH_WORD_SIZE *addr2;
-	int flag, prot, sect;
-	int i;
-
-	if ((s_first < 0) || (s_first > s_last)) {
-		if (info->flash_id == FLASH_UNKNOWN) {
-			printf("- missing\n");
-		} else {
-			printf("- no sectors to erase\n");
-		}
-		return 1;
-	}
-
-	if (info->flash_id == FLASH_UNKNOWN) {
-		printf("Can't erase unknown flash type - aborted\n");
-		return 1;
-	}
-
-	prot = 0;
-	for (sect = s_first; sect <= s_last; ++sect) {
-		if (info->protect[sect]) {
-			prot++;
-		}
-	}
-
-	if (prot) {
-		printf("- Warning: %d protected sectors will not be erased!\n",
-		       prot);
-	} else {
-		printf("\n");
-	}
-
-	/* Disable interrupts which might cause a timeout here */
-	flag = disable_interrupts();
-
-	/* Start erase on unprotected sectors */
-	for (sect = s_first; sect <= s_last; sect++) {
-		if (info->protect[sect] == 0) {	/* not protected */
-			addr2 = (CONFIG_SYS_FLASH_WORD_SIZE *) (info->start[sect]);
-
-			if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) {
-				addr[CONFIG_SYS_FLASH_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00AA00AA;
-				addr[CONFIG_SYS_FLASH_ADDR1] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00550055;
-				addr[CONFIG_SYS_FLASH_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00800080;
-				addr[CONFIG_SYS_FLASH_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00AA00AA;
-				addr[CONFIG_SYS_FLASH_ADDR1] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00550055;
-				addr2[0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00500050;	/* block erase */
-				for (i = 0; i < 50; i++)
-					udelay(1000);	/* wait 1 ms */
-			} else {
-				addr[CONFIG_SYS_FLASH_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00AA00AA;
-				addr[CONFIG_SYS_FLASH_ADDR1] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00550055;
-				addr[CONFIG_SYS_FLASH_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00800080;
-				addr[CONFIG_SYS_FLASH_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00AA00AA;
-				addr[CONFIG_SYS_FLASH_ADDR1] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00550055;
-				addr2[0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00300030;	/* sector erase */
-			}
-			/*
-			 * Wait for each sector to complete, it's more
-			 * reliable.  According to AMD Spec, you must
-			 * issue all erase commands within a specified
-			 * timeout.  This has been seen to fail, especially
-			 * if printf()s are included (for debug)!!
-			 */
-			wait_for_DQ7_1(info, sect);
-		}
-	}
-
-	/* re-enable interrupts if necessary */
-	if (flag)
-		enable_interrupts();
-
-	/* wait at least 80us - let's wait 1 ms */
-	udelay(1000);
-
-	/* reset to read mode */
-	addr = (CONFIG_SYS_FLASH_WORD_SIZE *) info->start[0];
-	addr[0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00F000F0;	/* reset bank */
-
-	printf(" done\n");
-	return 0;
-}
-
-/*-----------------------------------------------------------------------
- * Copy memory to flash, returns:
- * 0 - OK
- * 1 - write timeout
- * 2 - Flash not erased
- */
-int write_buff(flash_info_t * info, uchar * src, ulong addr, ulong cnt)
-{
-	ulong cp, wp, data;
-	int i, l, rc;
-
-	wp = (addr & ~3);	/* get lower word aligned address */
-
-	/*
-	 * handle unaligned start bytes
-	 */
-	if ((l = addr - wp) != 0) {
-		data = 0;
-		for (i = 0, cp = wp; i < l; ++i, ++cp) {
-			data = (data << 8) | (*(uchar *) cp);
-		}
-		for (; i < 4 && cnt > 0; ++i) {
-			data = (data << 8) | *src++;
-			--cnt;
-			++cp;
-		}
-		for (; cnt == 0 && i < 4; ++i, ++cp) {
-			data = (data << 8) | (*(uchar *) cp);
-		}
-
-		if ((rc = write_word(info, wp, data)) != 0) {
-			return rc;
-		}
-		wp += 4;
-	}
-
-	/*
-	 * handle word aligned part
-	 */
-	while (cnt >= 4) {
-		data = 0;
-		for (i = 0; i < 4; ++i) {
-			data = (data << 8) | *src++;
-		}
-		if ((rc = write_word(info, wp, data)) != 0) {
-			return rc;
-		}
-		wp += 4;
-		cnt -= 4;
-	}
-
-	if (cnt == 0) {
-		return 0;
-	}
-
-	/*
-	 * handle unaligned tail bytes
-	 */
-	data = 0;
-	for (i = 0, cp = wp; i < 4 && cnt > 0; ++i, ++cp) {
-		data = (data << 8) | *src++;
-		--cnt;
-	}
-	for (; i < 4; ++i, ++cp) {
-		data = (data << 8) | (*(uchar *) cp);
-	}
-
-	return (write_word(info, wp, data));
-}
-
-/*-----------------------------------------------------------------------
- * Copy memory to flash, returns:
- * 0 - OK
- * 1 - write timeout
- * 2 - Flash not erased
- */
-#ifdef FLASH_BASE1_PRELIM
-static int write_word(flash_info_t * info, ulong dest, ulong data)
-{
-	if (((info->flash_id & FLASH_TYPEMASK) == FLASH_AM320B) ||
-	    ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM320T) ||
-	    ((info->flash_id & FLASH_TYPEMASK) == FLASH_AMLV128U) ||
-	    ((info->flash_id & FLASH_TYPEMASK) == FLASH_S29GL128N) ||
-	    ((info->flash_id & FLASH_TYPEMASK) == FLASH_STMW320DT)) {
-		return write_word_2(info, dest, data);
-	} else {
-		return write_word_1(info, dest, data);
-	}
-}
-
-static int write_word_1(flash_info_t * info, ulong dest, ulong data)
-#else
-static int write_word(flash_info_t * info, ulong dest, ulong data)
-#endif
-{
-	ulong *data_ptr = &data;
-	volatile CONFIG_SYS_FLASH_WORD_SIZE *addr2 = (CONFIG_SYS_FLASH_WORD_SIZE *)(info->start[0]);
-	volatile CONFIG_SYS_FLASH_WORD_SIZE *dest2 = (CONFIG_SYS_FLASH_WORD_SIZE *)dest;
-	volatile CONFIG_SYS_FLASH_WORD_SIZE *data2 = (CONFIG_SYS_FLASH_WORD_SIZE *)data_ptr;
-	ulong start;
-	int i;
-
-	/* Check if Flash is (sufficiently) erased */
-	if ((*((vu_long *)dest) & data) != data) {
-		return 2;
-	}
-
-	for (i = 0; i < 4 / sizeof(CONFIG_SYS_FLASH_WORD_SIZE); i++) {
-		int flag;
-
-		/* Disable interrupts which might cause a timeout here */
-		flag = disable_interrupts();
-
-		addr2[CONFIG_SYS_FLASH_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00AA00AA;
-		addr2[CONFIG_SYS_FLASH_ADDR1] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00550055;
-		addr2[CONFIG_SYS_FLASH_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x00A000A0;
-
-		dest2[i] = data2[i];
-
-		/* re-enable interrupts if necessary */
-		if (flag)
-			enable_interrupts();
-
-		/* data polling for D7 */
-		start = get_timer(0);
-		while ((dest2[i] & (CONFIG_SYS_FLASH_WORD_SIZE) 0x00800080) !=
-		       (data2[i] & (CONFIG_SYS_FLASH_WORD_SIZE) 0x00800080)) {
-
-			if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
-				return 1;
-			}
-		}
-	}
-
-	return 0;
-}
-
-#ifdef FLASH_BASE1_PRELIM
-
-/*
- * The following code cannot be run from FLASH!
- */
-static ulong flash_get_size_2(vu_long * addr, flash_info_t * info)
-{
-	short i;
-	CONFIG_SYS_FLASH_CHAR_SIZE value;
-	ulong base = (ulong) addr;
-	volatile CONFIG_SYS_FLASH_WORD_SIZE *addr2 = (CONFIG_SYS_FLASH_WORD_SIZE *) addr;
-
-	DEBUGF("FLASH ADDR: %08x\n", (unsigned)addr);
-
-	/* Write auto select command: read Manufacturer ID */
-	addr2[CONFIG_SYS_FLASH_CHAR_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0xAAAAAAAA;
-	addr2[CONFIG_SYS_FLASH_CHAR_ADDR1] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x55555555;
-	addr2[CONFIG_SYS_FLASH_CHAR_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x90909090;
-	udelay(1000);
-
-	value = (CONFIG_SYS_FLASH_CHAR_SIZE)addr2[0];
-	DEBUGF("FLASH MANUFACT: %x\n", value);
-
-	switch (value) {
-	case (CONFIG_SYS_FLASH_CHAR_SIZE) AMD_MANUFACT:
-		info->flash_id = FLASH_MAN_AMD;
-		break;
-	case (CONFIG_SYS_FLASH_CHAR_SIZE) FUJ_MANUFACT:
-		info->flash_id = FLASH_MAN_FUJ;
-		break;
-	case (CONFIG_SYS_FLASH_CHAR_SIZE) SST_MANUFACT:
-		info->flash_id = FLASH_MAN_SST;
-		break;
-	case (CONFIG_SYS_FLASH_CHAR_SIZE) STM_MANUFACT:
-		info->flash_id = FLASH_MAN_STM;
-		break;
-	default:
-		info->flash_id = FLASH_UNKNOWN;
-		info->sector_count = 0;
-		info->size = 0;
-		return 0;		/* no or unknown flash */
-	}
-
-	value = (CONFIG_SYS_FLASH_CHAR_SIZE)addr2[2];	/* device ID */
-	DEBUGF("\nFLASH DEVICEID: %x\n", value);
-
-	switch (value) {
-	case (CONFIG_SYS_FLASH_CHAR_SIZE) AMD_ID_LV040B:
-		info->flash_id += FLASH_AM040;
-		info->sector_count = 8;
-		info->size = 0x0080000;	/* => 512 ko */
-		break;
-
-	case (CONFIG_SYS_FLASH_CHAR_SIZE) AMD_ID_F040B:
-		info->flash_id += FLASH_AM040;
-		info->sector_count = 8;
-		info->size = 0x0080000;	/* => 512 ko */
-		break;
-
-	case (CONFIG_SYS_FLASH_CHAR_SIZE) STM_ID_M29W040B:
-		info->flash_id += FLASH_AM040;
-		info->sector_count = 8;
-		info->size = 0x0080000;	/* => 512 ko */
-		break;
-
-	case (CONFIG_SYS_FLASH_CHAR_SIZE) AMD_ID_F016D:
-		info->flash_id += FLASH_AMD016;
-		info->sector_count = 32;
-		info->size = 0x00200000;
-		break;			/* => 2 MB */
-
-	case (CONFIG_SYS_FLASH_CHAR_SIZE) AMD_ID_LV033C:
-		info->flash_id += FLASH_AMDLV033C;
-		info->sector_count = 64;
-		info->size = 0x00400000;
-		break;			/* => 4 MB */
-
-	case (CONFIG_SYS_FLASH_CHAR_SIZE) AMD_ID_LV400T:
-		info->flash_id += FLASH_AM400T;
-		info->sector_count = 11;
-		info->size = 0x00080000;
-		break;			/* => 0.5 MB */
-
-	case (CONFIG_SYS_FLASH_CHAR_SIZE) AMD_ID_LV400B:
-		info->flash_id += FLASH_AM400B;
-		info->sector_count = 11;
-		info->size = 0x00080000;
-		break;			/* => 0.5 MB */
-
-	case (CONFIG_SYS_FLASH_CHAR_SIZE) AMD_ID_LV800T:
-		info->flash_id += FLASH_AM800T;
-		info->sector_count = 19;
-		info->size = 0x00100000;
-		break;			/* => 1 MB */
-
-	case (CONFIG_SYS_FLASH_CHAR_SIZE) AMD_ID_LV800B:
-		info->flash_id += FLASH_AM800B;
-		info->sector_count = 19;
-		info->size = 0x00100000;
-		break;			/* => 1 MB */
-
-	case (CONFIG_SYS_FLASH_CHAR_SIZE) AMD_ID_LV160T:
-		info->flash_id += FLASH_AM160T;
-		info->sector_count = 35;
-		info->size = 0x00200000;
-		break;			/* => 2 MB */
-
-	case (CONFIG_SYS_FLASH_CHAR_SIZE) AMD_ID_LV160B:
-		info->flash_id += FLASH_AM160B;
-		info->sector_count = 35;
-		info->size = 0x00200000;
-		break;			/* => 2 MB */
-	case (CONFIG_SYS_FLASH_CHAR_SIZE) AMD_ID_MIRROR:
-		if ((CONFIG_SYS_FLASH_CHAR_SIZE)addr2[0x1c] == (CONFIG_SYS_FLASH_CHAR_SIZE)AMD_ID_LV128U_2
-				&& (CONFIG_SYS_FLASH_CHAR_SIZE)addr2[0x1e] ==  (CONFIG_SYS_FLASH_CHAR_SIZE)AMD_ID_LV128U_3) {
-			info->flash_id += FLASH_AMLV128U;
-			info->sector_count = 256;
-			info->size = 0x01000000;
-		} else if ((CONFIG_SYS_FLASH_CHAR_SIZE)addr2[0x1c] == (CONFIG_SYS_FLASH_CHAR_SIZE)AMD_ID_GL128N_2
-				&& (CONFIG_SYS_FLASH_CHAR_SIZE)addr2[0x1e] ==  (CONFIG_SYS_FLASH_CHAR_SIZE)AMD_ID_GL128N_3 ) {
-			info->flash_id += FLASH_S29GL128N;
-			info->sector_count = 128;
-			info->size = 0x01000000;
-		}
-		else
-			info->flash_id = FLASH_UNKNOWN;
-		break;			/* => 2 MB */
-
-	default:
-		info->flash_id = FLASH_UNKNOWN;
-		return 0;		/* => no or unknown flash */
-	}
-
-	/* set up sector start address table */
-	if (((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) ||
-	    ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM040) ||
-	    ((info->flash_id & FLASH_TYPEMASK) == FLASH_AMD016)) {
-		for (i = 0; i < info->sector_count; i++)
-			info->start[i] = base + (i * 0x00010000);
-	} else if ((info->flash_id & FLASH_TYPEMASK) == FLASH_AMLV128U) {
-		for (i = 0; i < info->sector_count; i++)
-			info->start[i] = base + (i * 0x00010000);
-	} else if ((info->flash_id & FLASH_TYPEMASK) == FLASH_S29GL128N ) {
-		for (i = 0; i < info->sector_count; i++)
-			info->start[i] = base + (i * 0x00020000);
-	} else {
-		if (info->flash_id & FLASH_BTYPE) {
-			/* set sector offsets for bottom boot block type */
-			info->start[0] = base + 0x00000000;
-			info->start[1] = base + 0x00004000;
-			info->start[2] = base + 0x00006000;
-			info->start[3] = base + 0x00008000;
-			for (i = 4; i < info->sector_count; i++) {
-				info->start[i] =
-				    base + (i * 0x00010000) - 0x00030000;
-			}
-		} else {
-			/* set sector offsets for top boot block type */
-			i = info->sector_count - 1;
-			info->start[i--] = base + info->size - 0x00004000;
-			info->start[i--] = base + info->size - 0x00006000;
-			info->start[i--] = base + info->size - 0x00008000;
-			for (; i >= 0; i--) {
-				info->start[i] = base + i * 0x00010000;
-			}
-		}
-	}
-
-	/* check for protected sectors */
-	for (i = 0; i < info->sector_count; i++) {
-		/* read sector protection at sector address, (A7 .. A0) = 0x02 */
-		/* D0 = 1 if protected */
-		addr2 = (volatile CONFIG_SYS_FLASH_WORD_SIZE *)(info->start[i]);
-
-		/* For AMD29033C flash we need to resend the command of *
-		 * reading flash protection for upper 8 Mb of flash     */
-		if (i == 32) {
-			addr2[CONFIG_SYS_FLASH_CHAR_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0xAAAAAAAA;
-			addr2[CONFIG_SYS_FLASH_CHAR_ADDR1] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x55555555;
-			addr2[CONFIG_SYS_FLASH_CHAR_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x90909090;
-		}
-
-		if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST)
-			info->protect[i] = 0;
-		else
-			info->protect[i] = (CONFIG_SYS_FLASH_CHAR_SIZE)addr2[4] & 1;
-	}
-
-	/* issue bank reset to return to read mode */
-	addr2[0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0xF0F0F0F0;
-	return info->size;
-}
-
-static int wait_for_DQ7_2(flash_info_t * info, int sect)
-{
-	ulong start, now, last;
-	volatile CONFIG_SYS_FLASH_WORD_SIZE *addr =
-	    (CONFIG_SYS_FLASH_WORD_SIZE *) (info->start[sect]);
-
-	start = get_timer(0);
-	last = start;
-	while (((CONFIG_SYS_FLASH_WORD_SIZE)addr[0] & (CONFIG_SYS_FLASH_WORD_SIZE) 0x80808080) !=
-	       (CONFIG_SYS_FLASH_WORD_SIZE) 0x80808080) {
-		if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
-			printf("Timeout\n");
-			return -1;
-		}
-		/* show that we're waiting */
-		if ((now - last) > 1000) { /* every second */
-			putc('.');
-			last = now;
-		}
-	}
-	return 0;
-}
-
-static int flash_erase_2(flash_info_t * info, int s_first, int s_last)
-{
-	volatile CONFIG_SYS_FLASH_WORD_SIZE *addr = (CONFIG_SYS_FLASH_WORD_SIZE *) (info->start[0]);
-	volatile CONFIG_SYS_FLASH_WORD_SIZE *addr2;
-	int flag, prot, sect;
-	int i;
-
-	if ((s_first < 0) || (s_first > s_last)) {
-		if (info->flash_id == FLASH_UNKNOWN) {
-			printf("- missing\n");
-		} else {
-			printf("- no sectors to erase\n");
-		}
-		return 1;
-	}
-
-	if (info->flash_id == FLASH_UNKNOWN) {
-		printf("Can't erase unknown flash type - aborted\n");
-		return 1;
-	}
-
-	prot = 0;
-	for (sect = s_first; sect <= s_last; ++sect) {
-		if (info->protect[sect]) {
-			prot++;
-		}
-	}
-
-	if (prot) {
-		printf("- Warning: %d protected sectors will not be erased!\n",
-		       prot);
-	} else {
-		printf("\n");
-	}
-
-	/* Disable interrupts which might cause a timeout here */
-	flag = disable_interrupts();
-
-	/* Start erase on unprotected sectors */
-	for (sect = s_first; sect <= s_last; sect++) {
-		if (info->protect[sect] == 0) {	/* not protected */
-			addr2 = (CONFIG_SYS_FLASH_WORD_SIZE *) (info->start[sect]);
-
-			if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) {
-				addr[CONFIG_SYS_FLASH_CHAR_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0xAAAAAAAA;
-				addr[CONFIG_SYS_FLASH_CHAR_ADDR1] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x55555555;
-				addr[CONFIG_SYS_FLASH_CHAR_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x80808080;
-				addr[CONFIG_SYS_FLASH_CHAR_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0xAAAAAAAA;
-				addr[CONFIG_SYS_FLASH_CHAR_ADDR1] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x55555555;
-				addr2[0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x50505050;	/* block erase */
-				for (i = 0; i < 50; i++)
-					udelay(1000);	/* wait 1 ms */
-			} else {
-				addr[CONFIG_SYS_FLASH_CHAR_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0xAAAAAAAA;
-				addr[CONFIG_SYS_FLASH_CHAR_ADDR1] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x55555555;
-				addr[CONFIG_SYS_FLASH_CHAR_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x80808080;
-				addr[CONFIG_SYS_FLASH_CHAR_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0xAAAAAAAA;
-				addr[CONFIG_SYS_FLASH_CHAR_ADDR1] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x55555555;
-				addr2[0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x30303030;	/* sector erase */
-			}
-			/*
-			 * Wait for each sector to complete, it's more
-			 * reliable.  According to AMD Spec, you must
-			 * issue all erase commands within a specified
-			 * timeout.  This has been seen to fail, especially
-			 * if printf()s are included (for debug)!!
-			 */
-			wait_for_DQ7_2(info, sect);
-		}
-	}
-
-	/* re-enable interrupts if necessary */
-	if (flag)
-		enable_interrupts();
-
-	/* wait at least 80us - let's wait 1 ms */
-	udelay(1000);
-
-	/* reset to read mode */
-	addr = (CONFIG_SYS_FLASH_WORD_SIZE *) info->start[0];
-	addr[0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0xF0F0F0F0; /* reset bank */
-
-	printf(" done\n");
-	return 0;
-}
-
-static int write_word_2(flash_info_t * info, ulong dest, ulong data)
-{
-	ulong *data_ptr = &data;
-	volatile CONFIG_SYS_FLASH_WORD_SIZE *addr2 = (CONFIG_SYS_FLASH_WORD_SIZE *)(info->start[0]);
-	volatile CONFIG_SYS_FLASH_WORD_SIZE *dest2 = (CONFIG_SYS_FLASH_WORD_SIZE *)dest;
-	volatile CONFIG_SYS_FLASH_WORD_SIZE *data2 = (CONFIG_SYS_FLASH_WORD_SIZE *)data_ptr;
-	ulong start;
-	int i;
-
-	/* Check if Flash is (sufficiently) erased */
-	if ((*((vu_long *)dest) & data) != data) {
-		return 2;
-	}
-
-	for (i = 0; i < 4 / sizeof(CONFIG_SYS_FLASH_WORD_SIZE); i++) {
-		int flag;
-
-		/* Disable interrupts which might cause a timeout here */
-		flag = disable_interrupts();
-
-		addr2[CONFIG_SYS_FLASH_CHAR_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0xAAAAAAAA;
-		addr2[CONFIG_SYS_FLASH_CHAR_ADDR1] = (CONFIG_SYS_FLASH_WORD_SIZE) 0x55555555;
-		addr2[CONFIG_SYS_FLASH_CHAR_ADDR0] = (CONFIG_SYS_FLASH_WORD_SIZE) 0xA0A0A0A0;
-
-		dest2[i] = data2[i];
-
-		/* re-enable interrupts if necessary */
-		if (flag)
-			enable_interrupts();
-
-		/* data polling for D7 */
-		start = get_timer(0);
-		while ((dest2[i] & (CONFIG_SYS_FLASH_WORD_SIZE) 0x80808080) !=
-		       (data2[i] & (CONFIG_SYS_FLASH_WORD_SIZE) 0x80808080)) {
-
-			if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
-				return 1;
-			}
-		}
-	}
-
-	return 0;
-}
-
-#endif /* FLASH_BASE1_PRELIM */
diff --git a/board/amcc/taihu/lcd.c b/board/amcc/taihu/lcd.c
deleted file mode 100644
index c7c7fa4..0000000
--- a/board/amcc/taihu/lcd.c
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <config.h>
-#include <common.h>
-#include <command.h>
-#include <asm/io.h>
-#include <asm/ppc4xx-gpio.h>
-
-#define LCD_CMD_ADDR	0x50100002
-#define LCD_DATA_ADDR	0x50100003
-#define LCD_BLK_CTRL	CPLD_REG1_ADDR
-
-static char *amcc_logo = "AMCC 405EP TAIHU EVALUATION KIT";
-static int addr_flag = 0x80;
-
-static void lcd_bl_ctrl(char val)
-{
-	out_8((u8 *) LCD_BLK_CTRL, in_8((u8 *) LCD_BLK_CTRL) | val);
-}
-
-static void lcd_putc(int val)
-{
-	int i = 100;
-	char addr;
-
-	while (i--) {
-		if ((in_8((u8 *) LCD_CMD_ADDR) & 0x80) != 0x80) { /*BF = 1 ?*/
-			udelay(50);
-			break;
-		}
-		udelay(50);
-	}
-
-	if (in_8((u8 *) LCD_CMD_ADDR) & 0x80) {
-		printf("LCD is busy\n");
-		return;
-	}
-
-	addr = in_8((u8 *) LCD_CMD_ADDR);
-	udelay(50);
-	if ((addr != 0) && (addr % 0x10 == 0)) {
-		addr_flag ^= 0x40;
-		out_8((u8 *) LCD_CMD_ADDR, addr_flag);
-	}
-
-	udelay(50);
-	out_8((u8 *) LCD_DATA_ADDR, val);
-	udelay(50);
-}
-
-static void lcd_puts(char *s)
-{
-	char *p = s;
-	int i = 100;
-
-	while (i--) {
-		if ((in_8((u8 *) LCD_CMD_ADDR) & 0x80) != 0x80) { /*BF = 1 ?*/
-			udelay(50);
-			break;
-		}
-		udelay(50);
-	}
-
-	if (in_8((u8 *) LCD_CMD_ADDR) & 0x80) {
-		printf("LCD is busy\n");
-		return;
-	}
-
-	while (*p)
-		lcd_putc(*p++);
-}
-
-static void lcd_put_logo(void)
-{
-	int i = 100;
-	char *p = amcc_logo;
-
-	while (i--) {
-		if ((in_8((u8 *) LCD_CMD_ADDR) & 0x80) != 0x80) { /*BF = 1 ?*/
-			udelay(50);
-			break;
-		}
-		udelay(50);
-	}
-
-	if (in_8((u8 *) LCD_CMD_ADDR) & 0x80) {
-		printf("LCD is busy\n");
-		return;
-	}
-
-	out_8((u8 *) LCD_CMD_ADDR, 0x80);
-	while (*p)
-		lcd_putc(*p++);
-}
-
-int lcd_init(void)
-{
-	puts("LCD: ");
-	out_8((u8 *) LCD_CMD_ADDR, 0x38); /* set function:8-bit,2-line,5x7 font type */
-	udelay(50);
-	out_8((u8 *) LCD_CMD_ADDR, 0x0f); /* set display on,cursor on,blink on */
-	udelay(50);
-	out_8((u8 *) LCD_CMD_ADDR, 0x01); /* display clear */
-	udelay(2000);
-	out_8((u8 *) LCD_CMD_ADDR, 0x06); /* set entry */
-	udelay(50);
-	lcd_bl_ctrl(0x02);		/* set backlight on */
-	lcd_put_logo();
-	puts("ready\n");
-
-	return 0;
-}
-
-static int do_lcd_clear (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
-{
-	out_8((u8 *) LCD_CMD_ADDR, 0x01);
-	udelay(2000);
-
-	return 0;
-}
-
-static int do_lcd_puts (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
-{
-	if (argc < 2)
-		return cmd_usage(cmdtp);
-
-	lcd_puts(argv[1]);
-
-	return 0;
-}
-
-static int do_lcd_putc (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
-{
-	if (argc < 2)
-		return cmd_usage(cmdtp);
-
-	lcd_putc((char)argv[1][0]);
-
-	return 0;
-}
-
-static int do_lcd_cur (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
-{
-	ulong count;
-	ulong dir;
-	char cur_addr;
-
-	if (argc < 3)
-		return cmd_usage(cmdtp);
-
-	count = simple_strtoul(argv[1], NULL, 16);
-	if (count > 31) {
-		printf("unable to shift > 0x20\n");
-		count = 0;
-	}
-
-	dir = simple_strtoul(argv[2], NULL, 16);
-	cur_addr = in_8((u8 *) LCD_CMD_ADDR);
-	udelay(50);
-
-	if (dir == 0x0) {
-		if (addr_flag == 0x80) {
-			if (count >= (cur_addr & 0xf)) {
-				out_8((u8 *) LCD_CMD_ADDR, 0x80);
-				udelay(50);
-				count = 0;
-			}
-		} else {
-			if (count >= ((cur_addr & 0x0f) + 0x0f)) {
-				out_8((u8 *) LCD_CMD_ADDR, 0x80);
-				addr_flag = 0x80;
-				udelay(50);
-				count = 0x0;
-			} else if (count >= ( cur_addr & 0xf)) {
-				count -= cur_addr & 0xf ;
-				out_8((u8 *) LCD_CMD_ADDR, 0x80 | 0xf);
-				addr_flag = 0x80;
-				udelay(50);
-			}
-		}
-	} else {
-		if (addr_flag == 0x80) {
-			if (count >= (0x1f - (cur_addr & 0xf))) {
-				count = 0x0;
-				addr_flag = 0xc0;
-				out_8((u8 *) LCD_CMD_ADDR, 0xc0 | 0xf);
-				udelay(50);
-			} else if ((count + (cur_addr & 0xf ))>=  0x0f) {
-				count = count + (cur_addr & 0xf) - 0x0f;
-				addr_flag = 0xc0;
-				out_8((u8 *) LCD_CMD_ADDR, 0xc0);
-				udelay(50);
-			}
-		} else if ((count + (cur_addr & 0xf )) >= 0x0f) {
-			count = 0x0;
-			out_8((u8 *) LCD_CMD_ADDR, 0xC0 | 0x0F);
-			udelay(50);
-		}
-	}
-	while (count--) {
-		if (dir == 0)
-			out_8((u8 *) LCD_CMD_ADDR, 0x10);
-		else
-			out_8((u8 *) LCD_CMD_ADDR, 0x14);
-		udelay(50);
-	}
-
-	return 0;
-}
-
-U_BOOT_CMD(
-	lcd_cls, 1, 1, do_lcd_clear,
-	"lcd clear display",
-	""
-);
-
-U_BOOT_CMD(
-	lcd_puts, 2, 1, do_lcd_puts,
-	"display string on lcd",
-	"<string> - <string> to be displayed"
-);
-
-U_BOOT_CMD(
-	lcd_putc, 2, 1, do_lcd_putc,
-	"display char on lcd",
-	"<char> - <char> to be displayed"
-);
-
-U_BOOT_CMD(
-	lcd_cur, 3, 1, do_lcd_cur,
-	"shift cursor on lcd",
-	"<count> <dir> - shift cursor on lcd <count> times, direction is <dir> \n"
-	" <count> - 0..31\n"
-	" <dir>   - 0=backward 1=forward"
-);
diff --git a/board/amcc/taihu/taihu.c b/board/amcc/taihu/taihu.c
deleted file mode 100644
index fcb8936..0000000
--- a/board/amcc/taihu/taihu.c
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * (C) Copyright 2000-2005
- * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
- *
- * (C) Copyright 2005-2007
- * Beijing UD Technology Co., Ltd., taihusupport@amcc.com
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-#include <common.h>
-#include <command.h>
-#include <asm/processor.h>
-#include <asm/io.h>
-#include <spi.h>
-#include <netdev.h>
-#include <asm/ppc4xx-gpio.h>
-
-extern int lcd_init(void);
-
-/*
- * board_early_init_f
- */
-int board_early_init_f(void)
-{
-	lcd_init();
-
-	mtdcr(UIC0SR, 0xFFFFFFFF);	/* clear all ints */
-	mtdcr(UIC0ER, 0x00000000);	/* disable all ints */
-	mtdcr(UIC0CR, 0x00000000);
-	mtdcr(UIC0PR, 0xFFFF7F00);	/* set int polarities */
-	mtdcr(UIC0TR, 0x00000000);	/* set int trigger levels */
-	mtdcr(UIC0SR, 0xFFFFFFFF);	/* clear all ints */
-	mtdcr(UIC0VCR, 0x00000001);	/* set vect base=0,INT0 highest priority */
-
-	mtebc(PB3AP, CONFIG_SYS_EBC_PB3AP);	/* memory bank 3 (CPLD_LCM) initialization */
-	mtebc(PB3CR, CONFIG_SYS_EBC_PB3CR);
-
-	/*
-	 * Configure CPC0_PCI to enable PerWE as output
-	 * and enable the internal PCI arbiter
-	 */
-	mtdcr(CPC0_PCI, CPC0_PCI_SPE | CPC0_PCI_HOST_CFG_EN | CPC0_PCI_ARBIT_EN);
-
-	return 0;
-}
-
-/*
- * Check Board Identity:
- */
-int checkboard(void)
-{
-	char buf[64];
-	int i = getenv_f("serial#", buf, sizeof(buf));
-
-	puts("Board: Taihu - AMCC PPC405EP Evaluation Board");
-
-	if (i > 0) {
-		puts(", serial# ");
-		puts(buf);
-	}
-	putc('\n');
-
-	return 0;
-}
-
-static int do_sw_stat(cmd_tbl_t* cmd_tp, int flags, int argc, char * const argv[])
-{
-	char stat;
-	int i;
-
-	stat = in_8((u8 *) CPLD_REG0_ADDR);
-	printf("SW2 status: ");
-	for (i=0; i<4; i++) /* 4-position */
-		printf("%d:%s ", i, stat & (0x08 >> i)?"on":"off");
-	printf("\n");
-	return 0;
-}
-
-U_BOOT_CMD (
-	sw2_stat, 1, 1, do_sw_stat,
-	"show status of switch 2",
-	""
-);
-
-static int do_led_ctl(cmd_tbl_t* cmd_tp, int flags, int argc, char * const argv[])
-{
-	int led_no;
-
-	if (argc != 3)
-		return cmd_usage(cmd_tp);
-
-	led_no = simple_strtoul(argv[1], NULL, 16);
-	if (led_no != 1 && led_no != 2)
-		return cmd_usage(cmd_tp);
-
-	if (strcmp(argv[2],"off") == 0x0) {
-		if (led_no == 1)
-			gpio_write_bit(30, 1);
-		else
-			gpio_write_bit(31, 1);
-	} else if (strcmp(argv[2],"on") == 0x0) {
-		if (led_no == 1)
-			gpio_write_bit(30, 0);
-		else
-			gpio_write_bit(31, 0);
-	} else {
-		return cmd_usage(cmd_tp);
-	}
-
-	return 0;
-}
-
-U_BOOT_CMD (
-	led_ctl, 3, 1, do_led_ctl,
-	"make led 1 or 2  on or off",
-	"<led_no> <on/off>	-  make led <led_no> on/off,\n"
-	"\tled_no is 1 or 2"
-);
-
-#define SPI_CS_GPIO0	0
-#define SPI_SCLK_GPIO14	14
-#define SPI_DIN_GPIO15	15
-#define SPI_DOUT_GPIO16	16
-
-void spi_scl(int bit)
-{
-	gpio_write_bit(SPI_SCLK_GPIO14, bit);
-}
-
-void spi_sda(int bit)
-{
-	gpio_write_bit(SPI_DOUT_GPIO16, bit);
-}
-
-unsigned char spi_read(void)
-{
-	return (unsigned char)gpio_read_in_bit(SPI_DIN_GPIO15);
-}
-
-int spi_cs_is_valid(unsigned int bus, unsigned int cs)
-{
-	return bus == 0 && cs == 0;
-}
-
-void spi_cs_activate(struct spi_slave *slave)
-{
-	gpio_write_bit(SPI_CS_GPIO0, 1);
-}
-
-void spi_cs_deactivate(struct spi_slave *slave)
-{
-	gpio_write_bit(SPI_CS_GPIO0, 0);
-}
-
-#ifdef CONFIG_PCI
-static unsigned char int_lines[32] = {
-	29, 30, 27, 28, 29, 30, 25, 27,
-	29, 30, 27, 28, 29, 30, 27, 28,
-	29, 30, 27, 28, 29, 30, 27, 28,
-	29, 30, 27, 28, 29, 30, 27, 28};
-
-static void taihu_pci_fixup_irq(struct pci_controller *hose, pci_dev_t dev)
-{
-	unsigned char int_line = int_lines[PCI_DEV(dev) & 31];
-
-	pci_hose_write_config_byte(hose, dev, PCI_INTERRUPT_LINE, int_line);
-}
-
-int pci_pre_init(struct pci_controller *hose)
-{
-	hose->fixup_irq = taihu_pci_fixup_irq;
-	return 1;
-}
-#endif /* CONFIG_PCI */
-
-int board_eth_init(bd_t *bis)
-{
-	cpu_eth_init(bis);
-	return pci_eth_init(bis);
-}
diff --git a/board/amcc/taihu/update.c b/board/amcc/taihu/update.c
deleted file mode 100644
index ace217d..0000000
--- a/board/amcc/taihu/update.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <config.h>
-#include <common.h>
-#include <command.h>
-#include <asm/processor.h>
-#include <i2c.h>
-
-#define PCI_M66EN 0x10
-
-static uchar buf_33[] =
-{
-	0xb5,	/* 0x00:hce =1, bss = 0, pae=1, ppdv= 0b10,spe = 1,ebw=0b01*/
-	0x80,	/* 0x01~0x03:ptm1ms =0x80000001 */
-	0x00,
-	0x00,
-	0x00,	/* 0x04~0x06:ptm1la = 0x00000000 */
-	0x00,
-	0x00,
-	0x00,	/* 0x07~0x09:ptm2ma = 0x00000000 */
-	0x00,
-	0x00,
-	0x00,	/* 0x0a~0x0c:ptm2la = 0x00000000 */
-	0x00,
-	0x00,
-	0x10,	/* 0x0d~0x0e:vendor id 0x1014*/
-	0x14,
-	0x00,	/* 0x0f~0x10:device id 0x0000*/
-	0x00,
-	0x00,	/* 0x11:revision 0x00 */
-	0x00,	/* 0x12~0x14:class 0x000000 */
-	0x00,
-	0x00,
-	0x10,	/* 0x15~0x16:subsystem vendor id */
-	0xe8,
-	0x00,	/* 0x17~0x18:subsystem device id */
-	0x00,
-	0x61,	/* 0x19: opdv=0b01,cbdv=0b10,ccdv=0b00,ptm2ms_ena=0, ptm1ms_ena=1 */
-	0x68,	/* 0x1a: rpci=1,fbmul=0b1010,epdv=0b00 */
-	0x2d,	/* 0x1b: fwdvb=0b101,fwdva=0b101 */
-	0x82,	/* 0x1c: pllr=1,sscs=0,mpdv=0b00,tun[22-23]=0b10 */
-	0xbe,	/* 0x1d: tun[24-31]=0xbe */
-	0x00,
-	0x00
-};
-
-static uchar buf_66[] =
-{
-	0xb5,	/* 0x00:hce =1, bss = 0, pae=1, ppdv= 0b10,spe = 1,ebw=0b01*/
-	0x80,	/* 0x01~0x03:ptm1ms =0x80000001 */
-	0x00,
-	0x00,
-	0x00,	/* 0x04~0x06:ptm1la = 0x00000000 */
-	0x00,
-	0x00,
-	0x00,	/* 0x07~0x09:ptm2ma = 0x00000000 */
-	0x00,
-	0x00,
-	0x00,	/* 0x0a~0x0c:ptm2la = 0x00000000 */
-	0x00,
-	0x00,
-	0x10,	/* 0x0d~0x0e:vendor id 0x1014*/
-	0x14,
-	0x00,	/* 0x0f~0x10:device id 0x0000*/
-	0x00,
-	0x00,	/* 0x11:revision 0x00 */
-	0x00,	/* 0x12~0x14:class 0x000000 */
-	0x00,
-	0x00,
-	0x10,	/* 0x15~0x16:subsystem vendor id */
-	0xe8,
-	0x00,	/* 0x17~0x18:subsystem device id */
-	0x00,
-	0x61,	/* 0x19: opdv=0b01,cbdv=0b10,ccdv=0b00,ptm2ms_ena=0, ptm1ms_ena=1 */
-	0x68,	/* 0x1a: rpci=1,fbmul=0b1010,epdv=0b00 */
-	0x2d,	/* 0x1b: fwdvb=0b101,fwdva=0b101 */
-	0x82,	/* 0x1c: pllr=1,sscs=0,mpdv=0b00,tun[22-23]=0b10 */
-	0xbe,	/* 0x1d: tun[24-31]=0xbe */
-	0x00,
-	0x00
-};
-
-static int update_boot_eeprom(cmd_tbl_t* cmdtp, int flag, int argc, char * const argv[])
-{
-	ulong len = 0x20;
-	uchar chip = CONFIG_SYS_I2C_EEPROM_ADDR;
-	uchar *pbuf;
-	uchar base;
-	int i;
-
-	if ((*(volatile char*)CPLD_REG0_ADDR & PCI_M66EN) != PCI_M66EN) {
-		pbuf = buf_33;
-		base = 0x00;
-	} else {
-		pbuf = buf_66;
-		base = 0x40;
-	}
-
-	for (i = 0; i< len; i++, base++) {
-		if (i2c_write(chip, base, 1, &pbuf[i],1)!= 0) {
-			printf("i2c_write fail\n");
-			return 1;
-		}
-		udelay(11000);
-	}
-
-	return 0;
-}
-
-U_BOOT_CMD (
-	update_boot_eeprom, 1, 1, update_boot_eeprom,
-	"update boot eeprom content",
-	""
-);
diff --git a/board/amcc/taishan/Kconfig b/board/amcc/taishan/Kconfig
deleted file mode 100644
index 9ad8a4c..0000000
--- a/board/amcc/taishan/Kconfig
+++ /dev/null
@@ -1,16 +0,0 @@
-if TARGET_TAISHAN
-
-config SYS_BOARD
-	default "taishan"
-
-config SYS_VENDOR
-	default "amcc"
-
-config SYS_CONFIG_NAME
-	default "taishan"
-
-config DISPLAY_BOARDINFO
-	bool
-	default y
-
-endif
diff --git a/board/amcc/taishan/MAINTAINERS b/board/amcc/taishan/MAINTAINERS
deleted file mode 100644
index d9d80bf..0000000
--- a/board/amcc/taishan/MAINTAINERS
+++ /dev/null
@@ -1,6 +0,0 @@
-TAISHAN BOARD
-M:	Stefan Roese <sr@denx.de>
-S:	Maintained
-F:	board/amcc/taishan/
-F:	include/configs/taishan.h
-F:	configs/taishan_defconfig
diff --git a/board/amcc/taishan/Makefile b/board/amcc/taishan/Makefile
deleted file mode 100644
index 04e93cc..0000000
--- a/board/amcc/taishan/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-#
-# (C) Copyright 2007
-# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
-#
-# SPDX-License-Identifier:	GPL-2.0+
-#
-
-obj-y	= taishan.o lcd.o update.o showinfo.o
-extra-y	+= init.o
diff --git a/board/amcc/taishan/config.mk b/board/amcc/taishan/config.mk
deleted file mode 100644
index 6de8b59..0000000
--- a/board/amcc/taishan/config.mk
+++ /dev/null
@@ -1,20 +0,0 @@
-#
-# (C) Copyright 2004
-# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
-#
-# SPDX-License-Identifier:	GPL-2.0+
-#
-
-#
-# AMCC 440GX Reference Platform (Taishan) board
-#
-
-PLATFORM_CPPFLAGS += -DCONFIG_440=1
-
-ifeq ($(debug),1)
-PLATFORM_CPPFLAGS += -DDEBUG
-endif
-
-ifeq ($(dbcr),1)
-PLATFORM_CPPFLAGS += -DCONFIG_SYS_INIT_DBCR=0x8cff0000
-endif
diff --git a/board/amcc/taishan/init.S b/board/amcc/taishan/init.S
deleted file mode 100644
index ab1bb34..0000000
--- a/board/amcc/taishan/init.S
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * (C) Copyright 2007
- * Stefan Roese, DENX Software Engineering, sr@denx.de.
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <ppc_asm.tmpl>
-#include <asm/mmu.h>
-#include <config.h>
-#include <asm/ppc4xx.h>
-
-/**************************************************************************
- * TLB TABLE
- *
- * This table is used by the cpu boot code to setup the initial tlb
- * entries. Rather than make broad assumptions in the cpu source tree,
- * this table lets each board set things up however they like.
- *
- *  Pointer to the table is returned in r1
- *
- *************************************************************************/
-
-	.section .bootpg,"ax"
-	.globl tlbtab
-
-tlbtab:
-	tlbtab_start
-	tlbentry( 0xf0000000, SZ_256M, 0xf0000000, 1, AC_RWX | SA_IG)
-	tlbentry( CONFIG_SYS_PERIPHERAL_BASE, SZ_256M, 0x40000000, 1, AC_RW | SA_IG)
-	tlbentry( CONFIG_SYS_ISRAM_BASE, SZ_256K, 0x80000000, 0, AC_RWX )
-	tlbentry( CONFIG_SYS_SDRAM_BASE, SZ_256M, 0x00000000, 0, AC_RWX | SA_IG )
-	tlbentry( CONFIG_SYS_PCI_BASE, SZ_256M, 0x00000000, 2, AC_RW | SA_IG )
-	tlbentry( CONFIG_SYS_PCI_MEMBASE, SZ_256M, 0x00000000, 3, AC_RW | SA_IG )
-	tlbtab_end
diff --git a/board/amcc/taishan/lcd.c b/board/amcc/taishan/lcd.c
deleted file mode 100644
index 124b81e..0000000
--- a/board/amcc/taishan/lcd.c
+++ /dev/null
@@ -1,358 +0,0 @@
-/*
- * (C) Copyright 2007
- * Stefan Roese, DENX Software Engineering, sr@denx.de.
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <config.h>
-#include <common.h>
-#include <command.h>
-#include <i2c.h>
-#include <miiphy.h>
-
-#ifdef CONFIG_TAISHAN
-
-#define LCD_DELAY_NORMAL_US	100
-#define LCD_DELAY_NORMAL_MS	2
-#define LCD_CMD_ADDR		((volatile char *)(CONFIG_SYS_EBC2_LCM_BASE))
-#define LCD_DATA_ADDR		((volatile char *)(CONFIG_SYS_EBC2_LCM_BASE+1))
-#define LCD_BLK_CTRL		((volatile char *)(CONFIG_SYS_EBC1_FPGA_BASE+0x2))
-
-static int g_lcd_init_b = 0;
-static char *amcc_logo = "  AMCC TAISHAN  440GX EvalBoard";
-static char addr_flag = 0x80;
-
-static void lcd_bl_ctrl(char val)
-{
-	char cpld_val;
-
-	cpld_val = *LCD_BLK_CTRL;
-	*LCD_BLK_CTRL = val | cpld_val;
-}
-
-static void lcd_putc(char val)
-{
-	int i = 100;
-	char addr;
-
-	while (i--) {
-		if ((*LCD_CMD_ADDR & 0x80) != 0x80) {	/*BF = 1 ? */
-			udelay(LCD_DELAY_NORMAL_US);
-			break;
-		}
-		udelay(LCD_DELAY_NORMAL_US);
-	}
-
-	if (*LCD_CMD_ADDR & 0x80) {
-		printf("LCD is busy\n");
-		return;
-	}
-
-	addr = *LCD_CMD_ADDR;
-	udelay(LCD_DELAY_NORMAL_US);
-	if ((addr != 0) && (addr % 0x10 == 0)) {
-		addr_flag ^= 0x40;
-		*LCD_CMD_ADDR = addr_flag;
-	}
-
-	udelay(LCD_DELAY_NORMAL_US);
-	*LCD_DATA_ADDR = val;
-	udelay(LCD_DELAY_NORMAL_US);
-}
-
-static void lcd_puts(char *s)
-{
-	char *p = s;
-	int i = 100;
-
-	while (i--) {
-		if ((*LCD_CMD_ADDR & 0x80) != 0x80) {	/*BF = 1 ? */
-			udelay(LCD_DELAY_NORMAL_US);
-			break;
-		}
-		udelay(LCD_DELAY_NORMAL_US);
-	}
-
-	if (*LCD_CMD_ADDR & 0x80) {
-		printf("LCD is busy\n");
-		return;
-	}
-
-	while (*p)
-		lcd_putc(*p++);
-}
-
-static void lcd_put_logo(void)
-{
-	int i = 100;
-	char *p = amcc_logo;
-
-	while (i--) {
-		if ((*LCD_CMD_ADDR & 0x80) != 0x80) {	/*BF = 1 ? */
-			udelay(LCD_DELAY_NORMAL_US);
-			break;
-		}
-		udelay(LCD_DELAY_NORMAL_US);
-	}
-
-	if (*LCD_CMD_ADDR & 0x80) {
-		printf("LCD is busy\n");
-		return;
-	}
-
-	*LCD_CMD_ADDR = 0x80;
-	while (*p)
-		lcd_putc(*p++);
-}
-
-int lcd_init(void)
-{
-	if (g_lcd_init_b == 0) {
-		puts("LCD: ");
-		mdelay(100);	/* Waiting for the LCD initialize */
-
-		*LCD_CMD_ADDR = 0x38;	/*set function:8-bit,2-line,5x7 font type */
-		udelay(LCD_DELAY_NORMAL_US);
-
-		*LCD_CMD_ADDR = 0x0f;	/*set display on,cursor on,blink on */
-		udelay(LCD_DELAY_NORMAL_US);
-
-		*LCD_CMD_ADDR = 0x01;	/*display clear */
-		mdelay(LCD_DELAY_NORMAL_MS);
-
-		*LCD_CMD_ADDR = 0x06;	/*set entry */
-		udelay(LCD_DELAY_NORMAL_US);
-
-		lcd_bl_ctrl(0x02);
-		lcd_put_logo();
-
-		puts("  ready\n");
-		g_lcd_init_b = 1;
-	}
-
-	return 0;
-}
-
-static int do_lcd_test(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
-{
-	lcd_init();
-	return 0;
-}
-
-static int do_lcd_clear(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
-{
-	*LCD_CMD_ADDR = 0x01;
-	mdelay(LCD_DELAY_NORMAL_MS);
-	return 0;
-}
-static int do_lcd_puts(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
-{
-	if (argc < 2)
-		return cmd_usage(cmdtp);
-
-	lcd_puts(argv[1]);
-	return 0;
-}
-static int do_lcd_putc(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
-{
-	if (argc < 2)
-		return cmd_usage(cmdtp);
-
-	lcd_putc((char)argv[1][0]);
-	return 0;
-}
-static int do_lcd_cur(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
-{
-	ulong count;
-	ulong dir;
-	char cur_addr;
-
-	if (argc < 3)
-		return cmd_usage(cmdtp);
-
-	count = simple_strtoul(argv[1], NULL, 16);
-	if (count > 31) {
-		printf("unable to shift > 0x20\n");
-		count = 0;
-	}
-
-	dir = simple_strtoul(argv[2], NULL, 16);
-	cur_addr = *LCD_CMD_ADDR;
-	udelay(LCD_DELAY_NORMAL_US);
-	if (dir == 0x0) {
-		if (addr_flag == 0x80) {
-			if (count >= (cur_addr & 0xf)) {
-				*LCD_CMD_ADDR = 0x80;
-				udelay(LCD_DELAY_NORMAL_US);
-				count = 0;
-			}
-		} else {
-			if (count >= ((cur_addr & 0x0f) + 0x0f)) {
-				*LCD_CMD_ADDR = 0x80;
-				addr_flag = 0x80;
-				udelay(LCD_DELAY_NORMAL_US);
-				count = 0x0;
-			} else if (count >= (cur_addr & 0xf)) {
-				count -= cur_addr & 0xf;
-				*LCD_CMD_ADDR = 0x80 | 0xf;
-				addr_flag = 0x80;
-				udelay(LCD_DELAY_NORMAL_US);
-			}
-		}
-	} else {
-		if (addr_flag == 0x80) {
-			if (count >= (0x1f - (cur_addr & 0xf))) {
-				count = 0x0;
-				addr_flag = 0xc0;
-				*LCD_CMD_ADDR = 0xc0 | 0xf;
-				udelay(LCD_DELAY_NORMAL_US);
-			} else if ((count + (cur_addr & 0xf)) >= 0x0f) {
-				count = count + (cur_addr & 0xf) - 0x0f;
-				addr_flag = 0xc0;
-				*LCD_CMD_ADDR = 0xc0;
-				udelay(LCD_DELAY_NORMAL_US);
-			}
-		} else if ((count + (cur_addr & 0xf)) >= 0x0f) {
-			count = 0x0;
-			*LCD_CMD_ADDR = 0xc0 | 0xf;
-			udelay(LCD_DELAY_NORMAL_US);
-		}
-	}
-
-	while (count--) {
-		if (dir == 0) {
-			*LCD_CMD_ADDR = 0x10;
-		} else {
-			*LCD_CMD_ADDR = 0x14;
-		}
-		udelay(LCD_DELAY_NORMAL_US);
-	}
-
-	return 0;
-}
-
-U_BOOT_CMD(lcd_test, 1, 1, do_lcd_test, "lcd test display", "");
-U_BOOT_CMD(lcd_cls, 1, 1, do_lcd_clear, "lcd clear display", "");
-U_BOOT_CMD(lcd_puts, 2, 1, do_lcd_puts,
-	   "display string on lcd",
-	   "<string> - <string> to be displayed");
-U_BOOT_CMD(lcd_putc, 2, 1, do_lcd_putc,
-	   "display char on lcd",
-	   "<char> - <char> to be displayed");
-U_BOOT_CMD(lcd_cur, 3, 1, do_lcd_cur,
-	   "shift cursor on lcd",
-	   "<count> <dir>- shift cursor on lcd <count> times, direction is <dir> \n"
-	   " <count> - 0~31\n" " <dir> - 0,backward; 1, forward");
-
-#if 0 /* test-only */
-void set_phy_loopback_mode(void)
-{
-	char devemac2[32];
-	char devemac3[32];
-
-	sprintf(devemac2, "%s2", CONFIG_EMAC_DEV_NAME);
-	sprintf(devemac3, "%s3", CONFIG_EMAC_DEV_NAME);
-
-#if 0
-	unsigned short reg_short;
-
-	miiphy_read(devemac2, 0x1, 1, &reg_short);
-	if (reg_short & 0x04) {
-		/*
-		 * printf("EMAC2 link up,do nothing\n");
-		 */
-	} else {
-		udelay(1000);
-		miiphy_write(devemac2, 0x1, 0, 0x6000);
-		udelay(1000);
-		miiphy_read(devemac2, 0x1, 0, &reg_short);
-		if (reg_short != 0x6000) {
-			printf
-			    ("\nEMAC2 error set LOOPBACK mode error,reg2[0]=%x\n",
-			     reg_short);
-		}
-	}
-
-	miiphy_read(devemac3, 0x3, 1, &reg_short);
-	if (reg_short & 0x04) {
-		/*
-		 * printf("EMAC3 link up,do nothing\n");
-		 */
-	} else {
-		udelay(1000);
-		miiphy_write(devemac3, 0x3, 0, 0x6000);
-		udelay(1000);
-		miiphy_read(devemac3, 0x3, 0, &reg_short);
-		if (reg_short != 0x6000) {
-			printf
-			    ("\nEMAC3 error set LOOPBACK mode error,reg2[0]=%x\n",
-			     reg_short);
-		}
-	}
-#else
-	/* Set PHY as LOOPBACK MODE, for Linux emac initializing */
-	miiphy_write(devemac2, CONFIG_PHY2_ADDR, 0, 0x6000);
-	udelay(1000);
-	miiphy_write(devemac3, CONFIG_PHY3_ADDR, 0, 0x6000);
-	udelay(1000);
-#endif	/* 0 */
-}
-
-void set_phy_normal_mode(void)
-{
-	char devemac2[32];
-	char devemac3[32];
-	unsigned short reg_short;
-
-	sprintf(devemac2, "%s2", CONFIG_EMAC_DEV_NAME);
-	sprintf(devemac3, "%s3", CONFIG_EMAC_DEV_NAME);
-
-	/* Set phy of EMAC2 */
-	miiphy_read(devemac2, CONFIG_PHY2_ADDR, 0x16, &reg_short);
-	reg_short &= ~(0x7);
-	reg_short |= 0x6;	/* RGMII DLL Delay */
-	miiphy_write(devemac2, CONFIG_PHY2_ADDR, 0x16, reg_short);
-
-	miiphy_read(devemac2, CONFIG_PHY2_ADDR, 0x17, &reg_short);
-	reg_short &= ~(0x40);
-	miiphy_write(devemac2, CONFIG_PHY2_ADDR, 0x17, reg_short);
-
-	miiphy_write(devemac2, CONFIG_PHY2_ADDR, 0x1c, 0x74f0);
-
-	/* Set phy of EMAC3 */
-	miiphy_read(devemac3, CONFIG_PHY3_ADDR, 0x16, &reg_short);
-	reg_short &= ~(0x7);
-	reg_short |= 0x6;	/* RGMII DLL Delay */
-	miiphy_write(devemac3, CONFIG_PHY3_ADDR, 0x16, reg_short);
-
-	miiphy_read(devemac3, CONFIG_PHY3_ADDR, 0x17, &reg_short);
-	reg_short &= ~(0x40);
-	miiphy_write(devemac3, CONFIG_PHY3_ADDR, 0x17, reg_short);
-
-	miiphy_write(devemac3, CONFIG_PHY3_ADDR, 0x1c, 0x74f0);
-}
-#endif	/* 0 - test only */
-
-static int do_led_test_off(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
-{
-	volatile unsigned int *GpioOr =
-		(volatile unsigned int *)(CONFIG_SYS_PERIPHERAL_BASE + 0x700);
-	*GpioOr |= 0x00300000;
-	return 0;
-}
-
-static int do_led_test_on(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
-{
-	volatile unsigned int *GpioOr =
-		(volatile unsigned int *)(CONFIG_SYS_PERIPHERAL_BASE + 0x700);
-	*GpioOr &= ~0x00300000;
-	return 0;
-}
-
-U_BOOT_CMD(ledon, 1, 1, do_led_test_on,
-	   "led test light on", "");
-
-U_BOOT_CMD(ledoff, 1, 1, do_led_test_off,
-	   "led test light off", "");
-#endif
diff --git a/board/amcc/taishan/showinfo.c b/board/amcc/taishan/showinfo.c
deleted file mode 100644
index 53bfdf7..0000000
--- a/board/amcc/taishan/showinfo.c
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * (C) Copyright 2007
- * Stefan Roese, DENX Software Engineering, sr@denx.de.
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <config.h>
-#include <common.h>
-#include <command.h>
-#include <asm/processor.h>
-#include <pci.h>
-
-void show_reset_reg(void)
-{
-	unsigned long reg;
-
-	/* read clock regsiter */
-	printf("===== Display reset and initialize register Start =========\n");
-	mfcpr(CPR0_PLLC,reg);
-	printf("cpr_pllc   = %#010lx\n",reg);
-
-	mfcpr(CPR0_PLLD,reg);
-	printf("cpr_plld   = %#010lx\n",reg);
-
-	mfcpr(CPR0_PRIMAD0,reg);
-	printf("cpr_primad = %#010lx\n",reg);
-
-	mfcpr(CPR0_PRIMBD0,reg);
-	printf("cpr_primbd = %#010lx\n",reg);
-
-	mfcpr(CPR0_OPBD0,reg);
-	printf("cpr_opbd   = %#010lx\n",reg);
-
-	mfcpr(CPR0_PERD,reg);
-	printf("cpr_perd   = %#010lx\n",reg);
-
-	mfcpr(CPR0_MALD,reg);
-	printf("cpr_mald   = %#010lx\n",reg);
-
-	/* read sdr register */
-	mfsdr(SDR0_EBC,reg);
-	printf("SDR0_EBC    = %#010lx\n",reg);
-
-	mfsdr(SDR0_CP440,reg);
-	printf("SDR0_CP440  = %#010lx\n",reg);
-
-	mfsdr(SDR0_XCR,reg);
-	printf("SDR0_XCR    = %#010lx\n",reg);
-
-	mfsdr(SDR0_XPLLC,reg);
-	printf("SDR0_XPLLC  = %#010lx\n",reg);
-
-	mfsdr(SDR0_XPLLD,reg);
-	printf("SDR0_XPLLD  = %#010lx\n",reg);
-
-	mfsdr(SDR0_PFC0,reg);
-	printf("SDR0_PFC0   = %#010lx\n",reg);
-
-	mfsdr(SDR0_PFC1,reg);
-	printf("SDR0_PFC1   = %#010lx\n",reg);
-
-	mfsdr(SDR0_CUST0,reg);
-	printf("SDR0_CUST0  = %#010lx\n",reg);
-
-	mfsdr(SDR0_CUST1,reg);
-	printf("SDR0_CUST1  = %#010lx\n",reg);
-
-	mfsdr(SDR0_UART0,reg);
-	printf("SDR0_UART0  = %#010lx\n",reg);
-
-	mfsdr(SDR0_UART1,reg);
-	printf("SDR0_UART1  = %#010lx\n",reg);
-
-	printf("===== Display reset and initialize register End   =========\n");
-}
-
-void show_xbridge_info(void)
-{
-	unsigned long reg;
-
-	printf("PCI-X chip control registers\n");
-	mfsdr(SDR0_XCR, reg);
-	printf("SDR0_XCR    = %#010lx\n", reg);
-
-	mfsdr(SDR0_XPLLC, reg);
-	printf("SDR0_XPLLC  = %#010lx\n", reg);
-
-	mfsdr(SDR0_XPLLD, reg);
-	printf("SDR0_XPLLD  = %#010lx\n", reg);
-
-	printf("PCI-X Bridge Configure registers\n");
-	printf("PCIL0_VENDID            = %#06x\n", in16r(PCIL0_VENDID));
-	printf("PCIL0_DEVID             = %#06x\n", in16r(PCIL0_DEVID));
-	printf("PCIL0_CMD               = %#06x\n", in16r(PCIL0_CMD));
-	printf("PCIL0_STATUS            = %#06x\n", in16r(PCIL0_STATUS));
-	printf("PCIL0_REVID             = %#04x\n", in8(PCIL0_REVID));
-	printf("PCIL0_CACHELS           = %#04x\n", in8(PCIL0_CACHELS));
-	printf("PCIL0_LATTIM            = %#04x\n", in8(PCIL0_LATTIM));
-	printf("PCIL0_HDTYPE            = %#04x\n", in8(PCIL0_HDTYPE));
-	printf("PCIL0_BIST              = %#04x\n", in8(PCIL0_BIST));
-
-	printf("PCIL0_BAR0              = %#010lx\n", in32r(PCIL0_BAR0));
-	printf("PCIL0_BAR1              = %#010lx\n", in32r(PCIL0_BAR1));
-	printf("PCIL0_BAR2              = %#010lx\n", in32r(PCIL0_BAR2));
-	printf("PCIL0_BAR3              = %#010lx\n", in32r(PCIL0_BAR3));
-	printf("PCIL0_BAR4              = %#010lx\n", in32r(PCIL0_BAR4));
-	printf("PCIL0_BAR5              = %#010lx\n", in32r(PCIL0_BAR5));
-
-	printf("PCIL0_CISPTR            = %#010lx\n", in32r(PCIL0_CISPTR));
-	printf("PCIL0_SBSSYSVID         = %#010x\n", in16r(PCIL0_SBSYSVID));
-	printf("PCIL0_SBSSYSID          = %#010x\n", in16r(PCIL0_SBSYSID));
-	printf("PCIL0_EROMBA            = %#010lx\n", in32r(PCIL0_EROMBA));
-	printf("PCIL0_CAP               = %#04x\n", in8(PCIL0_CAP));
-	printf("PCIL0_INTLN             = %#04x\n", in8(PCIL0_INTLN));
-	printf("PCIL0_INTPN             = %#04x\n", in8(PCIL0_INTPN));
-	printf("PCIL0_MINGNT            = %#04x\n", in8(PCIL0_MINGNT));
-	printf("PCIL0_MAXLTNCY          = %#04x\n", in8(PCIL0_MAXLTNCY));
-
-	printf("PCIL0_BRDGOPT1          = %#010lx\n", in32r(PCIL0_BRDGOPT1));
-	printf("PCIL0_BRDGOPT2          = %#010lx\n", in32r(PCIL0_BRDGOPT2));
-
-	printf("PCIL0_POM0LAL           = %#010lx\n", in32r(PCIL0_POM0LAL));
-	printf("PCIL0_POM0LAH           = %#010lx\n", in32r(PCIL0_POM0LAH));
-	printf("PCIL0_POM0SA            = %#010lx\n", in32r(PCIL0_POM0SA));
-	printf("PCIL0_POM0PCILAL        = %#010lx\n", in32r(PCIL0_POM0PCIAL));
-	printf("PCIL0_POM0PCILAH        = %#010lx\n", in32r(PCIL0_POM0PCIAH));
-	printf("PCIL0_POM1LAL           = %#010lx\n", in32r(PCIL0_POM1LAL));
-	printf("PCIL0_POM1LAH           = %#010lx\n", in32r(PCIL0_POM1LAH));
-	printf("PCIL0_POM1SA            = %#010lx\n", in32r(PCIL0_POM1SA));
-	printf("PCIL0_POM1PCILAL        = %#010lx\n", in32r(PCIL0_POM1PCIAL));
-	printf("PCIL0_POM1PCILAH        = %#010lx\n", in32r(PCIL0_POM1PCIAH));
-	printf("PCIL0_POM2SA            = %#010lx\n", in32r(PCIL0_POM2SA));
-
-	printf("PCIL0_PIM0SA            = %#010lx\n", in32r(PCIL0_PIM0SA));
-	printf("PCIL0_PIM0LAL           = %#010lx\n", in32r(PCIL0_PIM0LAL));
-	printf("PCIL0_PIM0LAH           = %#010lx\n", in32r(PCIL0_PIM0LAH));
-	printf("PCIL0_PIM1SA            = %#010lx\n", in32r(PCIL0_PIM1SA));
-	printf("PCIL0_PIM1LAL           = %#010lx\n", in32r(PCIL0_PIM1LAL));
-	printf("PCIL0_PIM1LAH           = %#010lx\n", in32r(PCIL0_PIM1LAH));
-	printf("PCIL0_PIM2SA            = %#010lx\n", in32r(PCIL0_PIM1SA));
-	printf("PCIL0_PIM2LAL           = %#010lx\n", in32r(PCIL0_PIM1LAL));
-	printf("PCIL0_PIM2LAH           = %#010lx\n", in32r(PCIL0_PIM1LAH));
-
-	printf("PCIL0_XSTS              = %#010lx\n", in32r(PCIL0_STS));
-}
-
-int do_show_xbridge_info(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
-{
-	show_xbridge_info();
-	return 0;
-}
-
-U_BOOT_CMD(xbriinfo, 1, 1, do_show_xbridge_info,
-	   "Show PCIX bridge info", "");
-
-#define TAISHAN_PCI_DEV_ID0 0x800
-#define TAISHAN_PCI_DEV_ID1 0x1000
-
-void show_pcix_device_info(void)
-{
-	int ii;
-	int dev;
-	u8 capp;
-	u8 xcapid;
-	u16 status;
-	u16 xcommand;
-	u32 xstatus;
-
-	for (ii = 0; ii < 2; ii++) {
-		if (ii == 0)
-			dev = TAISHAN_PCI_DEV_ID0;
-		else
-			dev = TAISHAN_PCI_DEV_ID1;
-
-		pci_read_config_word(dev, PCI_STATUS, &status);
-		if (status & PCI_STATUS_CAP_LIST) {
-			pci_read_config_byte(dev, PCI_CAPABILITY_LIST, &capp);
-
-			pci_read_config_byte(dev, (int)(capp), &xcapid);
-			if (xcapid == 0x07) {
-				pci_read_config_word(dev, (int)(capp + 2),
-						     &xcommand);
-				pci_read_config_dword(dev, (int)(capp + 4),
-						      &xstatus);
-				printf("BUS0 dev%d Xcommand=%#06x,Xstatus=%#010x\n",
-				       (ii + 1), xcommand, xstatus);
-			} else {
-				printf("BUS0 dev%d PCI-X CAP ID error,"
-				       "CAP=%#04x,XCAPID=%#04x\n",
-				       (ii + 1), capp, xcapid);
-			}
-		} else {
-			printf("BUS0 dev%d not found PCI_STATUS_CAP_LIST supporting\n",
-			       ii + 1);
-		}
-	}
-
-}
-
-int do_show_pcix_device_info(cmd_tbl_t * cmdtp, int flag, int argc,
-			     char * const argv[])
-{
-	show_pcix_device_info();
-	return 0;
-}
-
-U_BOOT_CMD(xdevinfo, 1, 1, do_show_pcix_device_info,
-	   "Show PCIX Device info", "");
-
-extern void show_reset_reg(void);
-
-int do_show_reset_reg_info(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
-{
-	show_reset_reg();
-	return 0;
-}
-
-U_BOOT_CMD(resetinfo, 1, 1, do_show_reset_reg_info,
-	   "Show Reset REG info", "");
diff --git a/board/amcc/taishan/taishan.c b/board/amcc/taishan/taishan.c
deleted file mode 100644
index 5c8d9ec..0000000
--- a/board/amcc/taishan/taishan.c
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- *  Copyright (C) 2004 PaulReynolds@lhsolutions.com
- *
- * (C) Copyright 2007
- * Stefan Roese, DENX Software Engineering, sr@denx.de.
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <common.h>
-#include <asm/processor.h>
-#include <spd_sdram.h>
-#include <asm/ppc4xx-emac.h>
-#include <netdev.h>
-
-#ifdef CONFIG_SYS_INIT_SHOW_RESET_REG
-void show_reset_reg(void);
-#endif
-
-DECLARE_GLOBAL_DATA_PTR;
-
-int lcd_init(void);
-
-int board_early_init_f (void)
-{
-	unsigned long reg;
-	volatile unsigned int *GpioOdr;
-	volatile unsigned int *GpioTcr;
-	volatile unsigned int *GpioOr;
-
-	/*-------------------------------------------------------------------------+
-	  | Initialize EBC CONFIG
-	  +-------------------------------------------------------------------------*/
-	mtebc(EBC0_CFG, EBC_CFG_LE_UNLOCK |
-	      EBC_CFG_PTD_ENABLE | EBC_CFG_RTC_64PERCLK |
-	      EBC_CFG_ATC_PREVIOUS | EBC_CFG_DTC_PREVIOUS |
-	      EBC_CFG_CTC_PREVIOUS | EBC_CFG_EMC_DEFAULT |
-	      EBC_CFG_PME_DISABLE | EBC_CFG_PR_32);
-
-	/*-------------------------------------------------------------------------+
-	  | 64MB FLASH. Initialize bank 0 with default values.
-	  +-------------------------------------------------------------------------*/
-	mtebc(PB0AP, EBC_BXAP_BME_DISABLED|EBC_BXAP_TWT_ENCODE(15) |
-	      EBC_BXAP_BCE_DISABLE |
-	      EBC_BXAP_CSN_ENCODE(1) | EBC_BXAP_OEN_ENCODE(1) |
-	      EBC_BXAP_WBN_ENCODE(1) | EBC_BXAP_WBF_ENCODE(1) |
-	      EBC_BXAP_TH_ENCODE(3) | EBC_BXAP_RE_DISABLED |
-	      EBC_BXAP_BEM_WRITEONLY |
-	      EBC_BXAP_PEN_DISABLED);
-	mtebc(PB0CR, EBC_BXCR_BAS_ENCODE(CONFIG_SYS_FLASH_BASE) |
-	      EBC_BXCR_BS_64MB | EBC_BXCR_BU_RW|EBC_BXCR_BW_32BIT);
-
-	/*-------------------------------------------------------------------------+
-	  | FPGA. Initialize bank 1 with default values.
-	  +-------------------------------------------------------------------------*/
-	mtebc(PB1AP, EBC_BXAP_BME_DISABLED|EBC_BXAP_TWT_ENCODE(5) |
-	      EBC_BXAP_BCE_DISABLE |
-	      EBC_BXAP_CSN_ENCODE(1) | EBC_BXAP_OEN_ENCODE(1) |
-	      EBC_BXAP_WBN_ENCODE(1) | EBC_BXAP_WBF_ENCODE(1) |
-	      EBC_BXAP_TH_ENCODE(3) | EBC_BXAP_RE_DISABLED |
-	      EBC_BXAP_BEM_WRITEONLY |
-	      EBC_BXAP_PEN_DISABLED);
-	mtebc(PB1CR, EBC_BXCR_BAS_ENCODE(0x41000000) |
-	      EBC_BXCR_BS_1MB | EBC_BXCR_BU_RW | EBC_BXCR_BW_8BIT);
-
-	/*-------------------------------------------------------------------------+
-	  | LCM. Initialize bank 2 with default values.
-	  +-------------------------------------------------------------------------*/
-	mtebc(PB2AP, EBC_BXAP_BME_DISABLED | EBC_BXAP_TWT_ENCODE(64) |
-	      EBC_BXAP_BCE_DISABLE |
-	      EBC_BXAP_CSN_ENCODE(3) | EBC_BXAP_OEN_ENCODE(3) |
-	      EBC_BXAP_WBN_ENCODE(3) | EBC_BXAP_WBF_ENCODE(3) |
-	      EBC_BXAP_TH_ENCODE(7) | EBC_BXAP_RE_DISABLED |
-	      EBC_BXAP_BEM_WRITEONLY |
-	      EBC_BXAP_PEN_DISABLED);
-	mtebc(PB2CR, EBC_BXCR_BAS_ENCODE(0x42000000) |
-	      EBC_BXCR_BS_1MB | EBC_BXCR_BU_RW|EBC_BXCR_BW_8BIT);
-
-	/*-------------------------------------------------------------------------+
-	  | TMP. Initialize bank 3 with default values.
-	  +-------------------------------------------------------------------------*/
-	mtebc(PB3AP, EBC_BXAP_BME_DISABLED | EBC_BXAP_TWT_ENCODE(128) |
-	      EBC_BXAP_BCE_DISABLE |
-	      EBC_BXAP_CSN_ENCODE(3) | EBC_BXAP_OEN_ENCODE(3) |
-	      EBC_BXAP_WBN_ENCODE(3) | EBC_BXAP_WBF_ENCODE(3) |
-	      EBC_BXAP_TH_ENCODE(7) | EBC_BXAP_RE_DISABLED |
-	      EBC_BXAP_BEM_WRITEONLY |
-	      EBC_BXAP_PEN_DISABLED);
-	mtebc(PB3CR, EBC_BXCR_BAS_ENCODE(0x48000000) |
-	      EBC_BXCR_BS_64MB | EBC_BXCR_BU_RW | EBC_BXCR_BW_32BIT);
-
-	/*-------------------------------------------------------------------------+
-	  | Connector 4~7. Initialize bank 3~ 7 with default values.
-	  +-------------------------------------------------------------------------*/
-	mtebc(PB4AP,0);
-	mtebc(PB4CR,0);
-	mtebc(PB5AP,0);
-	mtebc(PB5CR,0);
-	mtebc(PB6AP,0);
-	mtebc(PB6CR,0);
-	mtebc(PB7AP,0);
-	mtebc(PB7CR,0);
-
-	/*--------------------------------------------------------------------
-	 * Setup the interrupt controller polarities, triggers, etc.
-	 *-------------------------------------------------------------------*/
-	/*
-	 * Because of the interrupt handling rework to handle 440GX interrupts
-	 * with the common code, we needed to change names of the UIC registers.
-	 * Here the new relationship:
-	 *
-	 * U-Boot name	440GX name
-	 * -----------------------
-	 * UIC0		UICB0
-	 * UIC1		UIC0
-	 * UIC2		UIC1
-	 * UIC3		UIC2
-	 */
-	mtdcr (UIC1SR, 0xffffffff);	/* clear all */
-	mtdcr (UIC1ER, 0x00000000);	/* disable all */
-	mtdcr (UIC1CR, 0x00000009);	/* SMI & UIC1 crit are critical */
-	mtdcr (UIC1PR, 0xfffffe13);	/* per ref-board manual */
-	mtdcr (UIC1TR, 0x01c00008);	/* per ref-board manual */
-	mtdcr (UIC1VR, 0x00000001);	/* int31 highest, base=0x000 */
-	mtdcr (UIC1SR, 0xffffffff);	/* clear all */
-
-	mtdcr (UIC2SR, 0xffffffff);	/* clear all */
-	mtdcr (UIC2ER, 0x00000000);	/* disable all */
-	mtdcr (UIC2CR, 0x00000000);	/* all non-critical */
-	mtdcr (UIC2PR, 0xffffe0ff);	/* per ref-board manual */
-	mtdcr (UIC2TR, 0x00ffc000);	/* per ref-board manual */
-	mtdcr (UIC2VR, 0x00000001);	/* int31 highest, base=0x000 */
-	mtdcr (UIC2SR, 0xffffffff);	/* clear all */
-
-	mtdcr (UIC3SR, 0xffffffff);	/* clear all */
-	mtdcr (UIC3ER, 0x00000000);	/* disable all */
-	mtdcr (UIC3CR, 0x00000000);	/* all non-critical */
-	mtdcr (UIC3PR, 0xffffffff);	/* per ref-board manual */
-	mtdcr (UIC3TR, 0x00ff8c0f);	/* per ref-board manual */
-	mtdcr (UIC3VR, 0x00000001);	/* int31 highest, base=0x000 */
-	mtdcr (UIC3SR, 0xffffffff);	/* clear all */
-
-	mtdcr (UIC0SR, 0xfc000000);	/* clear all */
-	mtdcr (UIC0ER, 0x00000000);	/* disable all */
-	mtdcr (UIC0CR, 0x00000000);	/* all non-critical */
-	mtdcr (UIC0PR, 0xfc000000);	/* */
-	mtdcr (UIC0TR, 0x00000000);	/* */
-	mtdcr (UIC0VR, 0x00000001);	/* */
-
-	/* Enable two GPIO 10~11 and TraceA signal */
-	mfsdr(SDR0_PFC0,reg);
-	reg |= 0x00300000;
-	mtsdr(SDR0_PFC0,reg);
-
-	mfsdr(SDR0_PFC1,reg);
-	reg |= 0x00100000;
-	mtsdr(SDR0_PFC1,reg);
-
-	/* Set GPIO 10 and 11 as output */
-	GpioOdr	= (volatile unsigned int*)(CONFIG_SYS_PERIPHERAL_BASE+0x718);
-	GpioTcr = (volatile unsigned int*)(CONFIG_SYS_PERIPHERAL_BASE+0x704);
-	GpioOr  = (volatile unsigned int*)(CONFIG_SYS_PERIPHERAL_BASE+0x700);
-
-	*GpioOdr &= ~(0x00300000);
-	*GpioTcr |= 0x00300000;
-	*GpioOr  |= 0x00300000;
-
-	return 0;
-}
-
-int misc_init_r(void)
-{
-	lcd_init();
-
-	return 0;
-}
-
-int checkboard (void)
-{
-	char buf[64];
-	int i = getenv_f("serial#", buf, sizeof(buf));
-
-	printf ("Board: Taishan - AMCC PPC440GX Evaluation Board");
-	if (i > 0) {
-		puts(", serial# ");
-		puts(buf);
-	}
-	putc ('\n');
-
-#ifdef CONFIG_SYS_INIT_SHOW_RESET_REG
-	show_reset_reg();
-#endif
-
-	return (0);
-}
-
-int board_eth_init(bd_t *bis)
-{
-	cpu_eth_init(bis);
-	return pci_eth_init(bis);
-}
diff --git a/board/amcc/taishan/update.c b/board/amcc/taishan/update.c
deleted file mode 100644
index 2738989..0000000
--- a/board/amcc/taishan/update.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * (C) Copyright 2007
- * Stefan Roese, DENX Software Engineering, sr@denx.de.
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <config.h>
-#include <common.h>
-#include <command.h>
-#include <asm/processor.h>
-#include <i2c.h>
-
-#if defined(CONFIG_TAISHAN)
-
-const uchar bootstrap_buf[16] = {
-	0x86,
-	0x78,
-	0xc1,
-	0xa6,
-	0x09,
-	0x67,
-	0x04,
-	0x63,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00
-};
-
-static int update_boot_eeprom(void)
-{
-	ulong len = 0x10;
-	uchar chip = CONFIG_SYS_BOOTSTRAP_IIC_ADDR;
-	uchar *pbuf = (uchar *)bootstrap_buf;
-	int ii, jj;
-
-	for (ii = 0; ii < len; ii++) {
-		if (i2c_write(chip, ii, 1, &pbuf[ii], 1) != 0) {
-			printf("i2c_write failed\n");
-			return -1;
-		}
-
-		/* wait 10ms */
-		for (jj = 0; jj < 10; jj++)
-			udelay(1000);
-	}
-	return 0;
-}
-
-int do_update_boot_eeprom(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
-{
-	return update_boot_eeprom();
-}
-
-U_BOOT_CMD(update_boot_eeprom, 1, 1, do_update_boot_eeprom,
-	   "update bootstrap eeprom content", "");
-#endif
diff --git a/common/board_r.c b/common/board_r.c
index a412bb7..c4fd3ea 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -449,6 +449,9 @@
 		env_relocate();
 	else
 		set_default_env(NULL);
+#ifdef CONFIG_OF_CONTROL
+	setenv_addr("fdtcontroladdr", gd->fdt_blob);
+#endif
 
 	/* Initialize from environment */
 	load_addr = getenv_ulong("loadaddr", 16, load_addr);
diff --git a/common/cmd_tpm.c b/common/cmd_tpm.c
index 97501cc..add6bfb 100644
--- a/common/cmd_tpm.c
+++ b/common/cmd_tpm.c
@@ -443,7 +443,6 @@
 TPM_COMMAND_NO_ARG(tpm_physical_enable)
 TPM_COMMAND_NO_ARG(tpm_physical_disable)
 
-#ifdef CONFIG_DM_TPM
 static int get_tpm(struct udevice **devp)
 {
 	int rc;
@@ -476,11 +475,11 @@
 
 	return 0;
 }
-#endif
 
 static int do_tpm_raw_transfer(cmd_tbl_t *cmdtp, int flag,
 		int argc, char * const argv[])
 {
+	struct udevice *dev;
 	void *command;
 	uint8_t response[1024];
 	size_t count, response_length = sizeof(response);
@@ -492,17 +491,11 @@
 		return CMD_RET_FAILURE;
 	}
 
-#ifdef CONFIG_DM_TPM
-	struct udevice *dev;
-
 	rc = get_tpm(&dev);
 	if (rc)
 		return rc;
 
 	rc = tpm_xfer(dev, command, count, response, &response_length);
-#else
-	rc = tis_sendrecv(command, count, response, &response_length);
-#endif
 	free(command);
 	if (!rc) {
 		puts("tpm response:\n");
@@ -657,9 +650,7 @@
 	U_BOOT_CMD_MKENT(cmd, 0, 1, do_tpm_ ## cmd, "", "")
 
 static cmd_tbl_t tpm_commands[] = {
-#ifdef CONFIG_DM_TPM
 	U_BOOT_CMD_MKENT(info, 0, 1, do_tpm_info, "", ""),
-#endif
 	U_BOOT_CMD_MKENT(init, 0, 1,
 			do_tpm_init, "", ""),
 	U_BOOT_CMD_MKENT(startup, 0, 1,
@@ -730,9 +721,7 @@
 "cmd args...\n"
 "    - Issue TPM command <cmd> with arguments <args...>.\n"
 "Admin Startup and State Commands:\n"
-#ifdef CONFIG_DM_TPM
 "  info - Show information about the TPM\n"
-#endif
 "  init\n"
 "    - Put TPM into a state where it waits for 'startup' command.\n"
 "  startup mode\n"
diff --git a/common/cmd_ubi.c b/common/cmd_ubi.c
index 0460b4c..753a4db 100644
--- a/common/cmd_ubi.c
+++ b/common/cmd_ubi.c
@@ -255,7 +255,7 @@
 
 	return 0;
 out_err:
-	ubi_err("cannot remove volume %s, error %d", volume, err);
+	ubi_err(ubi, "cannot remove volume %s, error %d", volume, err);
 	if (err < 0)
 		err = -err;
 	return err;
@@ -284,8 +284,8 @@
 			return -err;
 
 		if (err) {
-			ubi_warn("volume %d on UBI device %d is corrupted",
-					vol->vol_id, ubi->ubi_num);
+			ubi_warn(ubi, "volume %d on UBI device %d is corrupt",
+				 vol->vol_id, ubi->ubi_num);
 			vol->corrupted = 1;
 		}
 
diff --git a/common/cmd_usb.c b/common/cmd_usb.c
index 6bdbbc5..1ef55dc 100644
--- a/common/cmd_usb.c
+++ b/common/cmd_usb.c
@@ -281,7 +281,7 @@
 
 		if (!device_active(hub))
 			continue;
-		udev = dev_get_parentdata(hub);
+		udev = dev_get_parent_priv(hub);
 		if (udev->devnum == devnum)
 			return udev;
 
@@ -291,7 +291,7 @@
 			if (!device_active(hub))
 				continue;
 
-			udev = dev_get_parentdata(dev);
+			udev = dev_get_parent_priv(dev);
 			if (udev->devnum == devnum)
 				return udev;
 		}
@@ -407,7 +407,7 @@
 		if (!device_active(child))
 			continue;
 
-		udev = dev_get_parentdata(child);
+		udev = dev_get_parent_priv(child);
 
 		/* Ignore emulators, we only want real devices */
 		if (device_get_uclass_id(child) != UCLASS_USB_EMUL) {
@@ -553,7 +553,7 @@
 	struct udevice *child;
 	struct usb_device *udev;
 
-	udev = dev_get_parentdata(dev);
+	udev = dev_get_parent_priv(dev);
 	usb_display_desc(udev);
 	usb_display_config(udev);
 	for (device_find_first_child(dev, &child);
@@ -641,7 +641,7 @@
 
 			device_find_first_child(bus, &dev);
 			if (dev && device_active(dev)) {
-				udev = dev_get_parentdata(dev);
+				udev = dev_get_parent_priv(dev);
 				usb_show_tree(udev);
 			}
 		}
diff --git a/common/image.c b/common/image.c
index e607109..85c4f39 100644
--- a/common/image.c
+++ b/common/image.c
@@ -913,7 +913,7 @@
 	 * Look for an Android boot image.
 	 */
 	buf = map_sysmem(images->os.start, 0);
-	if (genimg_get_format(buf) == IMAGE_FORMAT_ANDROID)
+	if (buf && genimg_get_format(buf) == IMAGE_FORMAT_ANDROID)
 		select = argv[0];
 #endif
 
diff --git a/common/usb_hub.c b/common/usb_hub.c
index 415b45c..a92c9fb 100644
--- a/common/usb_hub.c
+++ b/common/usb_hub.c
@@ -230,7 +230,7 @@
 #ifdef CONFIG_DM_USB
 int hub_port_reset(struct udevice *dev, int port, unsigned short *portstat)
 {
-	struct usb_device *udev = dev_get_parentdata(dev);
+	struct usb_device *udev = dev_get_parent_priv(dev);
 
 	return legacy_hub_port_reset(udev, port, portstat);
 }
@@ -610,7 +610,7 @@
 #ifdef CONFIG_DM_USB
 int usb_hub_scan(struct udevice *hub)
 {
-	struct usb_device *udev = dev_get_parentdata(hub);
+	struct usb_device *udev = dev_get_parent_priv(hub);
 
 	return usb_hub_configure(udev);
 }
diff --git a/common/usb_storage.c b/common/usb_storage.c
index b390310..0ccaeb4 100644
--- a/common/usb_storage.c
+++ b/common/usb_storage.c
@@ -1408,7 +1408,7 @@
 
 static int usb_mass_storage_probe(struct udevice *dev)
 {
-	struct usb_device *udev = dev_get_parentdata(dev);
+	struct usb_device *udev = dev_get_parent_priv(dev);
 	int ret;
 
 	usb_disable_asynch(1); /* asynch transfer not allowed */
diff --git a/configs/controlcenterd_36BIT_SDCARD_DEVELOP_defconfig b/configs/controlcenterd_36BIT_SDCARD_DEVELOP_defconfig
index c8ab862..58566c1 100644
--- a/configs/controlcenterd_36BIT_SDCARD_DEVELOP_defconfig
+++ b/configs/controlcenterd_36BIT_SDCARD_DEVELOP_defconfig
@@ -6,6 +6,8 @@
 # CONFIG_CMD_FLASH is not set
 CONFIG_CMD_TPM=y
 CONFIG_SPI_FLASH=y
+CONFIG_DM=y
+CONFIG_DM_TPM=y
 CONFIG_TPM_ATMEL_TWI=y
 CONFIG_TPM_AUTH_SESSIONS=y
 CONFIG_TPM=y
diff --git a/configs/controlcenterd_36BIT_SDCARD_defconfig b/configs/controlcenterd_36BIT_SDCARD_defconfig
index 21c0eab..56a4910 100644
--- a/configs/controlcenterd_36BIT_SDCARD_defconfig
+++ b/configs/controlcenterd_36BIT_SDCARD_defconfig
@@ -6,6 +6,8 @@
 # CONFIG_CMD_FLASH is not set
 CONFIG_CMD_TPM=y
 CONFIG_SPI_FLASH=y
+CONFIG_DM=y
+CONFIG_DM_TPM=y
 CONFIG_TPM_ATMEL_TWI=y
 CONFIG_TPM_AUTH_SESSIONS=y
 CONFIG_TPM=y
diff --git a/configs/controlcenterd_TRAILBLAZER_DEVELOP_defconfig b/configs/controlcenterd_TRAILBLAZER_DEVELOP_defconfig
index c3a0920..cbf43ef 100644
--- a/configs/controlcenterd_TRAILBLAZER_DEVELOP_defconfig
+++ b/configs/controlcenterd_TRAILBLAZER_DEVELOP_defconfig
@@ -7,6 +7,8 @@
 # CONFIG_CMD_FLASH is not set
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_TPM=y
+CONFIG_DM=y
+CONFIG_DM_TPM=y
 CONFIG_TPM_ATMEL_TWI=y
 CONFIG_TPM_AUTH_SESSIONS=y
 CONFIG_TPM=y
diff --git a/configs/controlcenterd_TRAILBLAZER_defconfig b/configs/controlcenterd_TRAILBLAZER_defconfig
index 08aae9a..e897422 100644
--- a/configs/controlcenterd_TRAILBLAZER_defconfig
+++ b/configs/controlcenterd_TRAILBLAZER_defconfig
@@ -7,6 +7,8 @@
 # CONFIG_CMD_FLASH is not set
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_TPM=y
+CONFIG_DM=y
+CONFIG_DM_TPM=y
 CONFIG_TPM_ATMEL_TWI=y
 CONFIG_TPM_AUTH_SESSIONS=y
 CONFIG_TPM=y
diff --git a/configs/ebony_defconfig b/configs/ebony_defconfig
deleted file mode 100644
index db93555..0000000
--- a/configs/ebony_defconfig
+++ /dev/null
@@ -1,3 +0,0 @@
-CONFIG_PPC=y
-CONFIG_4xx=y
-CONFIG_TARGET_EBONY=y
diff --git a/configs/nyan-big_defconfig b/configs/nyan-big_defconfig
index 2dd2930..4f31c1c 100644
--- a/configs/nyan-big_defconfig
+++ b/configs/nyan-big_defconfig
@@ -20,7 +20,7 @@
 CONFIG_SPI_FLASH=y
 CONFIG_TEGRA114_SPI=y
 CONFIG_DM_TPM=y
-CONFIG_TPM_TIS_I2C=y
+CONFIG_TPM_TIS_INFINEON=y
 CONFIG_USB=y
 CONFIG_DM_USB=y
 CONFIG_DISPLAY_PORT=y
diff --git a/configs/ocotea_defconfig b/configs/ocotea_defconfig
deleted file mode 100644
index 34518cd..0000000
--- a/configs/ocotea_defconfig
+++ /dev/null
@@ -1,3 +0,0 @@
-CONFIG_PPC=y
-CONFIG_4xx=y
-CONFIG_TARGET_OCOTEA=y
diff --git a/configs/peach-pi_defconfig b/configs/peach-pi_defconfig
index dfdf61b..6eff072 100644
--- a/configs/peach-pi_defconfig
+++ b/configs/peach-pi_defconfig
@@ -30,7 +30,7 @@
 CONFIG_SOUND_MAX98095=y
 CONFIG_SOUND_WM8994=y
 CONFIG_DM_TPM=y
-CONFIG_TPM_TIS_I2C=y
+CONFIG_TPM_TIS_INFINEON=y
 CONFIG_USB=y
 CONFIG_DM_USB=y
 CONFIG_VIDEO_BRIDGE=y
diff --git a/configs/peach-pit_defconfig b/configs/peach-pit_defconfig
index 01c4f37..24bc161 100644
--- a/configs/peach-pit_defconfig
+++ b/configs/peach-pit_defconfig
@@ -30,7 +30,7 @@
 CONFIG_SOUND_MAX98095=y
 CONFIG_SOUND_WM8994=y
 CONFIG_DM_TPM=y
-CONFIG_TPM_TIS_I2C=y
+CONFIG_TPM_TIS_INFINEON=y
 CONFIG_USB=y
 CONFIG_DM_USB=y
 CONFIG_VIDEO_BRIDGE=y
diff --git a/configs/snow_defconfig b/configs/snow_defconfig
index c4e2f61..0c9ca8b 100644
--- a/configs/snow_defconfig
+++ b/configs/snow_defconfig
@@ -39,7 +39,7 @@
 CONFIG_SOUND_MAX98095=y
 CONFIG_SOUND_WM8994=y
 CONFIG_DM_TPM=y
-CONFIG_TPM_TIS_I2C=y
+CONFIG_TPM_TIS_INFINEON=y
 CONFIG_USB=y
 CONFIG_DM_USB=y
 CONFIG_VIDEO_BRIDGE=y
diff --git a/configs/spring_defconfig b/configs/spring_defconfig
index 4acadf3..47bc643 100644
--- a/configs/spring_defconfig
+++ b/configs/spring_defconfig
@@ -39,7 +39,7 @@
 CONFIG_SOUND_MAX98095=y
 CONFIG_SOUND_WM8994=y
 CONFIG_DM_TPM=y
-CONFIG_TPM_TIS_I2C=y
+CONFIG_TPM_TIS_INFINEON=y
 CONFIG_USB=y
 CONFIG_DM_USB=y
 CONFIG_VIDEO_BRIDGE=y
diff --git a/configs/taihu_defconfig b/configs/taihu_defconfig
deleted file mode 100644
index ac83725..0000000
--- a/configs/taihu_defconfig
+++ /dev/null
@@ -1,3 +0,0 @@
-CONFIG_PPC=y
-CONFIG_4xx=y
-CONFIG_TARGET_TAIHU=y
diff --git a/configs/taishan_defconfig b/configs/taishan_defconfig
deleted file mode 100644
index e956c6f..0000000
--- a/configs/taishan_defconfig
+++ /dev/null
@@ -1,3 +0,0 @@
-CONFIG_PPC=y
-CONFIG_4xx=y
-CONFIG_TARGET_TAISHAN=y
diff --git a/configs/zynq_microzed_defconfig b/configs/zynq_microzed_defconfig
index e9c3209..9cb2ca1 100644
--- a/configs/zynq_microzed_defconfig
+++ b/configs/zynq_microzed_defconfig
@@ -11,3 +11,5 @@
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_OF_EMBED=y
 CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_SPI_FLASH=y
+CONFIG_ZYNQ_QSPI=y
diff --git a/configs/zynq_zc702_defconfig b/configs/zynq_zc702_defconfig
index 0abb7a8..c4922f3 100644
--- a/configs/zynq_zc702_defconfig
+++ b/configs/zynq_zc702_defconfig
@@ -10,3 +10,5 @@
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_OF_EMBED=y
 CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_SPI_FLASH=y
+CONFIG_ZYNQ_QSPI=y
diff --git a/configs/zynq_zc706_defconfig b/configs/zynq_zc706_defconfig
index d67f507..b4c076c 100644
--- a/configs/zynq_zc706_defconfig
+++ b/configs/zynq_zc706_defconfig
@@ -11,3 +11,5 @@
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_OF_EMBED=y
 CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_SPI_FLASH=y
+CONFIG_ZYNQ_QSPI=y
diff --git a/configs/zynq_zc70x_defconfig b/configs/zynq_zc70x_defconfig
index 37c249f..97f8a5d 100644
--- a/configs/zynq_zc70x_defconfig
+++ b/configs/zynq_zc70x_defconfig
@@ -11,3 +11,5 @@
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_OF_EMBED=y
 CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_SPI_FLASH=y
+CONFIG_ZYNQ_QSPI=y
diff --git a/configs/zynq_zc770_xm010_defconfig b/configs/zynq_zc770_xm010_defconfig
index 0e826bb..61106df 100644
--- a/configs/zynq_zc770_xm010_defconfig
+++ b/configs/zynq_zc770_xm010_defconfig
@@ -13,3 +13,4 @@
 CONFIG_OF_EMBED=y
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_SPI_FLASH=y
+CONFIG_ZYNQ_QSPI=y
diff --git a/configs/zynq_zed_defconfig b/configs/zynq_zed_defconfig
index 886b4a5..5e128fb 100644
--- a/configs/zynq_zed_defconfig
+++ b/configs/zynq_zed_defconfig
@@ -11,3 +11,5 @@
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_OF_EMBED=y
 CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_SPI_FLASH=y
+CONFIG_ZYNQ_QSPI=y
diff --git a/doc/README.fdt-control b/doc/README.fdt-control
index e6d5ed0..29fd56a 100644
--- a/doc/README.fdt-control
+++ b/doc/README.fdt-control
@@ -156,7 +156,10 @@
 Be aware that this environment variable is checked prior to relocation,
 when only the compiled-in environment is available. Therefore it is not
 possible to define this variable in the saved SPI/NAND flash
-environment, for example (it will be ignored).
+environment, for example (it will be ignored). After relocation, this
+variable will be set to the address of the newly relocated fdt blob.
+It is read-only and cannot be changed. It can optionally be used to
+control the boot process of Linux with bootm/bootz commands.
 
 To use this, put something like this in your board header file:
 
diff --git a/doc/README.scrapyard b/doc/README.scrapyard
index 2760f60..cddaff6 100644
--- a/doc/README.scrapyard
+++ b/doc/README.scrapyard
@@ -12,6 +12,10 @@
 
 Board            Arch        CPU            Commit      Removed     Last known maintainer/contact
 =================================================================================================
+ocotea           powerpc     ppc4xx         -           -           Stefan Roese <sr@denx.de>
+taishan          powerpc     ppc4xx         -           -           Stefan Roese <sr@denx.de>
+ebony            powerpc     ppc4xx         -           -           Stefan Roese <sr@denx.de>
+taihu            powerpc     ppc4xx         -           -           John Otken <jotken@softadvances.com>
 lcd4_lwmon5      powerpc     ppc4xx         b6b5e394    2015-10-02  Stefan Roese <sr@denx.de>
 da830evm         arm         arm926ejs      d7e8b2b9    2015-09-12  Nick Thompson <nick.thompson@gefanuc.com>
 wireless_space   arm         arm926ejs      b352182a    2015-09-12  Albert ARIBAUD <albert.u.boot@aribaud.net>
diff --git a/doc/device-tree-bindings/spi/spi-zynq-qspi.txt b/doc/device-tree-bindings/spi/spi-zynq-qspi.txt
new file mode 100644
index 0000000..47472fd
--- /dev/null
+++ b/doc/device-tree-bindings/spi/spi-zynq-qspi.txt
@@ -0,0 +1,26 @@
+Xilinx Zynq QSPI controller Device Tree Bindings
+-------------------------------------------------
+
+Required properties:
+- compatible		: Should be "xlnx,zynq-qspi-1.0".
+- reg			: Physical base address and size of QSPI registers map.
+- interrupts		: Property with a value describing the interrupt
+			  number.
+- interrupt-parent	: Must be core interrupt controller
+- clock-names		: List of input clock names - "ref_clk", "pclk"
+			  (See clock bindings for details).
+- clocks		: Clock phandles (see clock bindings for details).
+
+Optional properties:
+- num-cs		: Number of chip selects used.
+
+Example:
+	qspi@e000d000 {
+		compatible = "xlnx,zynq-qspi-1.0";
+		clock-names = "ref_clk", "pclk";
+		clocks = <&clkc 10>, <&clkc 43>;
+		interrupt-parent = <&intc>;
+		interrupts = <0 19 4>;
+		num-cs = <1>;
+		reg = <0xe000d000 0x1000>;
+	} ;
diff --git a/doc/driver-model/usb-info.txt b/doc/driver-model/usb-info.txt
index 66f2dae..e07e5ba 100644
--- a/doc/driver-model/usb-info.txt
+++ b/doc/driver-model/usb-info.txt
@@ -84,7 +84,7 @@
 	This holds information about a device on the bus. All devices have
 	this structure, even the root hub. The controller itself does not
 	have this structure. You can access it for a device 'dev' with
-	dev_get_parentdata(dev). It matches the old structure except that the
+	dev_get_parent_priv(dev). It matches the old structure except that the
 	parent and child information is not present (since driver model
 	handles that). Once the device is set up, you can find the device
 	descriptor and current configuration descriptor in this structure.
@@ -279,7 +279,7 @@
 uclass, they share some common elements with controllers:
 
 - they both attach private data to their children (struct usb_device,
-accessible for a child with dev_get_parentdata(child))
+accessible for a child with dev_get_parent_priv(child))
 - they both use usb_child_pre_probe() to set up their children as proper USB
 devices
 
diff --git a/drivers/core/device.c b/drivers/core/device.c
index a3dc2ca..758f390 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -395,7 +395,7 @@
 	return dev->uclass_priv;
 }
 
-void *dev_get_parentdata(struct udevice *dev)
+void *dev_get_parent_priv(struct udevice *dev)
 {
 	if (!dev) {
 		dm_warn("%s: null device\n", __func__);
diff --git a/drivers/i2c/zynq_i2c.c b/drivers/i2c/zynq_i2c.c
index b3264af..380863b 100644
--- a/drivers/i2c/zynq_i2c.c
+++ b/drivers/i2c/zynq_i2c.c
@@ -297,11 +297,15 @@
 	return 0;
 }
 
+#ifdef CONFIG_ZYNQ_I2C0
 U_BOOT_I2C_ADAP_COMPLETE(zynq_0, zynq_i2c_init, zynq_i2c_probe, zynq_i2c_read,
 			 zynq_i2c_write, zynq_i2c_set_bus_speed,
 			 CONFIG_SYS_I2C_ZYNQ_SPEED, CONFIG_SYS_I2C_ZYNQ_SLAVE,
 			 0)
+#endif
+#ifdef CONFIG_ZYNQ_I2C1
 U_BOOT_I2C_ADAP_COMPLETE(zynq_1, zynq_i2c_init, zynq_i2c_probe, zynq_i2c_read,
 			 zynq_i2c_write, zynq_i2c_set_bus_speed,
 			 CONFIG_SYS_I2C_ZYNQ_SPEED, CONFIG_SYS_I2C_ZYNQ_SLAVE,
 			 1)
+#endif
diff --git a/drivers/misc/cros_ec_spi.c b/drivers/misc/cros_ec_spi.c
index 0686925..253d91a 100644
--- a/drivers/misc/cros_ec_spi.c
+++ b/drivers/misc/cros_ec_spi.c
@@ -24,7 +24,7 @@
 int cros_ec_spi_packet(struct udevice *udev, int out_bytes, int in_bytes)
 {
 	struct cros_ec_dev *dev = dev_get_uclass_priv(udev);
-	struct spi_slave *slave = dev_get_parentdata(dev->dev);
+	struct spi_slave *slave = dev_get_parent_priv(dev->dev);
 	ulong start;
 	uint8_t byte;
 	int rv;
@@ -84,7 +84,7 @@
 		     uint8_t **dinp, int din_len)
 {
 	struct cros_ec_dev *dev = dev_get_uclass_priv(udev);
-	struct spi_slave *slave = dev_get_parentdata(dev->dev);
+	struct spi_slave *slave = dev_get_parent_priv(dev->dev);
 	int in_bytes = din_len + 4;	/* status, length, checksum, trailer */
 	uint8_t *out;
 	uint8_t *p;
diff --git a/drivers/mtd/cfi_flash.c b/drivers/mtd/cfi_flash.c
index 50983b8..fc7a878 100644
--- a/drivers/mtd/cfi_flash.c
+++ b/drivers/mtd/cfi_flash.c
@@ -335,34 +335,34 @@
 	switch (info->portwidth) {
 	case FLASH_CFI_8BIT:
 		debug ("fwc addr %p cmd %x %x 8bit x %d bit\n", addr, cmd,
-		       cword.c, info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
-		flash_write8(cword.c, addr);
+		       cword.w8, info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
+		flash_write8(cword.w8, addr);
 		break;
 	case FLASH_CFI_16BIT:
 		debug ("fwc addr %p cmd %x %4.4x 16bit x %d bit\n", addr,
-		       cmd, cword.w,
+		       cmd, cword.w16,
 		       info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
-		flash_write16(cword.w, addr);
+		flash_write16(cword.w16, addr);
 		break;
 	case FLASH_CFI_32BIT:
-		debug ("fwc addr %p cmd %x %8.8lx 32bit x %d bit\n", addr,
-		       cmd, cword.l,
+		debug ("fwc addr %p cmd %x %8.8x 32bit x %d bit\n", addr,
+		       cmd, cword.w32,
 		       info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
-		flash_write32(cword.l, addr);
+		flash_write32(cword.w32, addr);
 		break;
 	case FLASH_CFI_64BIT:
 #ifdef DEBUG
 		{
 			char str[20];
 
-			print_longlong (str, cword.ll);
+			print_longlong (str, cword.w64);
 
 			debug ("fwrite addr %p cmd %x %s 64 bit x %d bit\n",
 			       addr, cmd, str,
 			       info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
 		}
 #endif
-		flash_write64(cword.ll, addr);
+		flash_write64(cword.w64, addr);
 		break;
 	}
 
@@ -393,16 +393,16 @@
 	debug ("is= cmd %x(%c) addr %p ", cmd, cmd, addr);
 	switch (info->portwidth) {
 	case FLASH_CFI_8BIT:
-		debug ("is= %x %x\n", flash_read8(addr), cword.c);
-		retval = (flash_read8(addr) == cword.c);
+		debug ("is= %x %x\n", flash_read8(addr), cword.w8);
+		retval = (flash_read8(addr) == cword.w8);
 		break;
 	case FLASH_CFI_16BIT:
-		debug ("is= %4.4x %4.4x\n", flash_read16(addr), cword.w);
-		retval = (flash_read16(addr) == cword.w);
+		debug ("is= %4.4x %4.4x\n", flash_read16(addr), cword.w16);
+		retval = (flash_read16(addr) == cword.w16);
 		break;
 	case FLASH_CFI_32BIT:
-		debug ("is= %8.8x %8.8lx\n", flash_read32(addr), cword.l);
-		retval = (flash_read32(addr) == cword.l);
+		debug ("is= %8.8x %8.8x\n", flash_read32(addr), cword.w32);
+		retval = (flash_read32(addr) == cword.w32);
 		break;
 	case FLASH_CFI_64BIT:
 #ifdef DEBUG
@@ -411,11 +411,11 @@
 			char str2[20];
 
 			print_longlong (str1, flash_read64(addr));
-			print_longlong (str2, cword.ll);
+			print_longlong (str2, cword.w64);
 			debug ("is= %s %s\n", str1, str2);
 		}
 #endif
-		retval = (flash_read64(addr) == cword.ll);
+		retval = (flash_read64(addr) == cword.w64);
 		break;
 	default:
 		retval = 0;
@@ -439,16 +439,16 @@
 	flash_make_cmd (info, cmd, &cword);
 	switch (info->portwidth) {
 	case FLASH_CFI_8BIT:
-		retval = ((flash_read8(addr) & cword.c) == cword.c);
+		retval = ((flash_read8(addr) & cword.w8) == cword.w8);
 		break;
 	case FLASH_CFI_16BIT:
-		retval = ((flash_read16(addr) & cword.w) == cword.w);
+		retval = ((flash_read16(addr) & cword.w16) == cword.w16);
 		break;
 	case FLASH_CFI_32BIT:
-		retval = ((flash_read32(addr) & cword.l) == cword.l);
+		retval = ((flash_read32(addr) & cword.w32) == cword.w32);
 		break;
 	case FLASH_CFI_64BIT:
-		retval = ((flash_read64(addr) & cword.ll) == cword.ll);
+		retval = ((flash_read64(addr) & cword.w64) == cword.w64);
 		break;
 	default:
 		retval = 0;
@@ -680,33 +680,33 @@
 
 	switch (info->portwidth) {
 	case FLASH_CFI_8BIT:
-		cword->c = c;
+		cword->w8 = c;
 		break;
 	case FLASH_CFI_16BIT:
 #if defined(__LITTLE_ENDIAN) && !defined(CONFIG_SYS_WRITE_SWAPPED_DATA)
 		w = c;
 		w <<= 8;
-		cword->w = (cword->w >> 8) | w;
+		cword->w16 = (cword->w16 >> 8) | w;
 #else
-		cword->w = (cword->w << 8) | c;
+		cword->w16 = (cword->w16 << 8) | c;
 #endif
 		break;
 	case FLASH_CFI_32BIT:
 #if defined(__LITTLE_ENDIAN) && !defined(CONFIG_SYS_WRITE_SWAPPED_DATA)
 		l = c;
 		l <<= 24;
-		cword->l = (cword->l >> 8) | l;
+		cword->w32 = (cword->w32 >> 8) | l;
 #else
-		cword->l = (cword->l << 8) | c;
+		cword->w32 = (cword->w32 << 8) | c;
 #endif
 		break;
 	case FLASH_CFI_64BIT:
 #if defined(__LITTLE_ENDIAN) && !defined(CONFIG_SYS_WRITE_SWAPPED_DATA)
 		ll = c;
 		ll <<= 56;
-		cword->ll = (cword->ll >> 8) | ll;
+		cword->w64 = (cword->w64 >> 8) | ll;
 #else
-		cword->ll = (cword->ll << 8) | c;
+		cword->w64 = (cword->w64 << 8) | c;
 #endif
 		break;
 	}
@@ -753,16 +753,16 @@
 	/* Check if Flash is (sufficiently) erased */
 	switch (info->portwidth) {
 	case FLASH_CFI_8BIT:
-		flag = ((flash_read8(dstaddr) & cword.c) == cword.c);
+		flag = ((flash_read8(dstaddr) & cword.w8) == cword.w8);
 		break;
 	case FLASH_CFI_16BIT:
-		flag = ((flash_read16(dstaddr) & cword.w) == cword.w);
+		flag = ((flash_read16(dstaddr) & cword.w16) == cword.w16);
 		break;
 	case FLASH_CFI_32BIT:
-		flag = ((flash_read32(dstaddr) & cword.l) == cword.l);
+		flag = ((flash_read32(dstaddr) & cword.w32) == cword.w32);
 		break;
 	case FLASH_CFI_64BIT:
-		flag = ((flash_read64(dstaddr) & cword.ll) == cword.ll);
+		flag = ((flash_read64(dstaddr) & cword.w64) == cword.w64);
 		break;
 	default:
 		flag = 0;
@@ -800,16 +800,16 @@
 
 	switch (info->portwidth) {
 	case FLASH_CFI_8BIT:
-		flash_write8(cword.c, dstaddr);
+		flash_write8(cword.w8, dstaddr);
 		break;
 	case FLASH_CFI_16BIT:
-		flash_write16(cword.w, dstaddr);
+		flash_write16(cword.w16, dstaddr);
 		break;
 	case FLASH_CFI_32BIT:
-		flash_write32(cword.l, dstaddr);
+		flash_write32(cword.w32, dstaddr);
 		break;
 	case FLASH_CFI_64BIT:
-		flash_write64(cword.ll, dstaddr);
+		flash_write64(cword.w64, dstaddr);
 		break;
 	}
 
@@ -1115,7 +1115,7 @@
 			if (use_flash_status_poll(info)) {
 				cfiword_t cword;
 				void *dest;
-				cword.ll = 0xffffffffffffffffULL;
+				cword.w64 = 0xffffffffffffffffULL;
 				dest = flash_map(info, sect, 0);
 				st = flash_status_poll(info, &cword, dest,
 						       info->erase_blk_tout, "erase");
@@ -1305,7 +1305,7 @@
 
 	/* handle unaligned start */
 	if ((aln = addr - wp) != 0) {
-		cword.l = 0;
+		cword.w32 = 0;
 		p = (uchar *)wp;
 		for (i = 0; i < aln; ++i)
 			flash_add_byte (info, &cword, flash_read8(p + i));
@@ -1332,7 +1332,7 @@
 	while (cnt >= info->portwidth) {
 		/* prohibit buffer write when buffer_size is 1 */
 		if (info->buffer_size == 1) {
-			cword.l = 0;
+			cword.w32 = 0;
 			for (i = 0; i < info->portwidth; i++)
 				flash_add_byte (info, &cword, *src++);
 			if ((rc = flash_write_cfiword (info, wp, cword)) != 0)
@@ -1359,7 +1359,7 @@
 	}
 #else
 	while (cnt >= info->portwidth) {
-		cword.l = 0;
+		cword.w32 = 0;
 		for (i = 0; i < info->portwidth; i++) {
 			flash_add_byte (info, &cword, *src++);
 		}
@@ -1381,7 +1381,7 @@
 	/*
 	 * handle unaligned tail bytes
 	 */
-	cword.l = 0;
+	cword.w32 = 0;
 	p = (uchar *)wp;
 	for (i = 0; (i < info->portwidth) && (cnt > 0); ++i) {
 		flash_add_byte (info, &cword, *src++);
diff --git a/drivers/mtd/spi/sf_dataflash.c b/drivers/mtd/spi/sf_dataflash.c
index 3111f4f..b2a56da 100644
--- a/drivers/mtd/spi/sf_dataflash.c
+++ b/drivers/mtd/spi/sf_dataflash.c
@@ -577,7 +577,7 @@
  */
 static int spi_dataflash_probe(struct udevice *dev)
 {
-	struct spi_slave *spi = dev_get_parentdata(dev);
+	struct spi_slave *spi = dev_get_parent_priv(dev);
 	struct spi_flash *spi_flash;
 	struct flash_info *info;
 	u8 idcode[5];
diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h
index 9c95d56..8a3e5ec 100644
--- a/drivers/mtd/spi/sf_internal.h
+++ b/drivers/mtd/spi/sf_internal.h
@@ -51,6 +51,11 @@
 
 #define SST_WR		(SST_BP | SST_WP)
 
+enum spi_nor_option_flags {
+	SNOR_F_SST_WR		= (1 << 0),
+	SNOR_F_USE_FSR		= (1 << 1),
+};
+
 #define SPI_FLASH_3B_ADDR_LEN		3
 #define SPI_FLASH_CMD_LEN		(1 + SPI_FLASH_3B_ADDR_LEN)
 #define SPI_FLASH_16MB_BOUN		0x1000000
diff --git a/drivers/mtd/spi/sf_ops.c b/drivers/mtd/spi/sf_ops.c
index 900ec1f..f2a9244 100644
--- a/drivers/mtd/spi/sf_ops.c
+++ b/drivers/mtd/spi/sf_ops.c
@@ -41,6 +41,20 @@
 	return 0;
 }
 
+static int read_fsr(struct spi_flash *flash, u8 *fsr)
+{
+	int ret;
+	const u8 cmd = CMD_FLAG_STATUS;
+
+	ret = spi_flash_read_common(flash, &cmd, 1, fsr, 1);
+	if (ret < 0) {
+		debug("SF: fail to read flag status register\n");
+		return ret;
+	}
+
+	return 0;
+}
+
 int spi_flash_cmd_write_status(struct spi_flash *flash, u8 ws)
 {
 	u8 cmd;
@@ -95,15 +109,14 @@
 #endif
 
 #ifdef CONFIG_SPI_FLASH_BAR
-static int spi_flash_cmd_bankaddr_write(struct spi_flash *flash, u8 bank_sel)
+static int spi_flash_write_bank(struct spi_flash *flash, u32 offset)
 {
-	u8 cmd;
+	u8 cmd, bank_sel;
 	int ret;
 
-	if (flash->bank_curr == bank_sel) {
-		debug("SF: not require to enable bank%d\n", bank_sel);
-		return 0;
-	}
+	bank_sel = offset / (SPI_FLASH_16MB_BOUN << flash->shift);
+	if (bank_sel == flash->bank_curr)
+		goto bar_end;
 
 	cmd = flash->bank_write_cmd;
 	ret = spi_flash_write_common(flash, &cmd, 1, &bank_sel, 1);
@@ -111,25 +124,10 @@
 		debug("SF: fail to write bank register\n");
 		return ret;
 	}
-	flash->bank_curr = bank_sel;
-
-	return 0;
-}
-
-static int spi_flash_bank(struct spi_flash *flash, u32 offset)
-{
-	u8 bank_sel;
-	int ret;
 
-	bank_sel = offset / (SPI_FLASH_16MB_BOUN << flash->shift);
-
-	ret = spi_flash_cmd_bankaddr_write(flash, bank_sel);
-	if (ret) {
-		debug("SF: fail to set bank%d\n", bank_sel);
-		return ret;
-	}
-
-	return bank_sel;
+bar_end:
+	flash->bank_curr = bank_sel;
+	return flash->bank_curr;
 }
 #endif
 
@@ -155,72 +153,65 @@
 }
 #endif
 
-static int spi_flash_poll_status(struct spi_slave *spi, unsigned long timeout,
-				 u8 cmd, u8 poll_bit)
+static int spi_flash_sr_ready(struct spi_flash *flash)
 {
-	unsigned long timebase;
-	unsigned long flags = SPI_XFER_BEGIN;
+	u8 sr;
 	int ret;
-	u8 status;
-	u8 check_status = 0x0;
 
-	if (cmd == CMD_FLAG_STATUS)
-		check_status = poll_bit;
-
-#ifdef CONFIG_SF_DUAL_FLASH
-	if (spi->flags & SPI_XFER_U_PAGE)
-		flags |= SPI_XFER_U_PAGE;
-#endif
-	ret = spi_xfer(spi, 8, &cmd, NULL, flags);
-	if (ret) {
-		debug("SF: fail to read %s status register\n",
-		      cmd == CMD_READ_STATUS ? "read" : "flag");
+	ret = spi_flash_cmd_read_status(flash, &sr);
+	if (ret < 0)
 		return ret;
-	}
 
-	timebase = get_timer(0);
-	do {
-		WATCHDOG_RESET();
+	return !(sr & STATUS_WIP);
+}
 
-		ret = spi_xfer(spi, 8, NULL, &status, 0);
-		if (ret)
-			return -1;
+static int spi_flash_fsr_ready(struct spi_flash *flash)
+{
+	u8 fsr;
+	int ret;
 
-		if ((status & poll_bit) == check_status)
-			break;
+	ret = read_fsr(flash, &fsr);
+	if (ret < 0)
+		return ret;
 
-	} while (get_timer(timebase) < timeout);
+	return fsr & STATUS_PEC;
+}
 
-	spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END);
+static int spi_flash_ready(struct spi_flash *flash)
+{
+	int sr, fsr;
 
-	if ((status & poll_bit) == check_status)
-		return 0;
+	sr = spi_flash_sr_ready(flash);
+	if (sr < 0)
+		return sr;
 
-	/* Timed out */
-	debug("SF: time out!\n");
-	return -1;
+	fsr = 1;
+	if (flash->flags & SNOR_F_USE_FSR) {
+		fsr = spi_flash_fsr_ready(flash);
+		if (fsr < 0)
+			return fsr;
+	}
+
+	return sr && fsr;
 }
 
 int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout)
 {
-	struct spi_slave *spi = flash->spi;
-	int ret;
-	u8 poll_bit = STATUS_WIP;
-	u8 cmd = CMD_READ_STATUS;
+	int timebase, ret;
 
-	ret = spi_flash_poll_status(spi, timeout, cmd, poll_bit);
-	if (ret < 0)
-		return ret;
+	timebase = get_timer(0);
 
-	if (flash->poll_cmd == CMD_FLAG_STATUS) {
-		poll_bit = STATUS_PEC;
-		cmd = CMD_FLAG_STATUS;
-		ret = spi_flash_poll_status(spi, timeout, cmd, poll_bit);
+	while (get_timer(timebase) < timeout) {
+		ret = spi_flash_ready(flash);
 		if (ret < 0)
 			return ret;
+		if (ret)
+			return 0;
 	}
 
-	return 0;
+	printf("SF: Timeout!\n");
+
+	return -ETIMEDOUT;
 }
 
 int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd,
@@ -285,7 +276,7 @@
 			spi_flash_dual_flash(flash, &erase_addr);
 #endif
 #ifdef CONFIG_SPI_FLASH_BAR
-		ret = spi_flash_bank(flash, erase_addr);
+		ret = spi_flash_write_bank(flash, erase_addr);
 		if (ret < 0)
 			return ret;
 #endif
@@ -327,7 +318,7 @@
 			spi_flash_dual_flash(flash, &write_addr);
 #endif
 #ifdef CONFIG_SPI_FLASH_BAR
-		ret = spi_flash_bank(flash, write_addr);
+		ret = spi_flash_write_bank(flash, write_addr);
 		if (ret < 0)
 			return ret;
 #endif
@@ -422,9 +413,10 @@
 			spi_flash_dual_flash(flash, &read_addr);
 #endif
 #ifdef CONFIG_SPI_FLASH_BAR
-		bank_sel = spi_flash_bank(flash, read_addr);
-		if (bank_sel < 0)
+		ret = spi_flash_write_bank(flash, read_addr);
+		if (ret < 0)
 			return ret;
+		bank_sel = flash->bank_curr;
 #endif
 		remain_len = ((SPI_FLASH_16MB_BOUN << flash->shift) *
 				(bank_sel + 1)) - offset;
diff --git a/drivers/mtd/spi/sf_params.c b/drivers/mtd/spi/sf_params.c
index 8f5bdda..4f37e33 100644
--- a/drivers/mtd/spi/sf_params.c
+++ b/drivers/mtd/spi/sf_params.c
@@ -35,6 +35,11 @@
 	{"GD25Q64B",	   0xc84017, 0x0,	64 * 1024,   128, RD_NORM,		    SECT_4K},
 	{"GD25LQ32",	   0xc86016, 0x0,	64 * 1024,    64, RD_NORM,		    SECT_4K},
 #endif
+#ifdef CONFIG_SPI_FLASH_ISSI		/* ISSI */
+	{"IS25LP032",	   0x9d6016, 0x0,	64 * 1024,    64, RD_NORM,			  0},
+	{"IS25LP064",	   0x9d6017, 0x0,	64 * 1024,   128, RD_NORM,			  0},
+	{"IS25LP128",	   0x9d6018, 0x0,	64 * 1024,   256, RD_NORM,			  0},
+#endif
 #ifdef CONFIG_SPI_FLASH_MACRONIX	/* MACRONIX */
 	{"MX25L2006E",	   0xc22012, 0x0,	64 * 1024,     4, RD_NORM,			  0},
 	{"MX25L4005",	   0xc22013, 0x0,	64 * 1024,     8, RD_NORM,			  0},
diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c
index 954376d..c000c53 100644
--- a/drivers/mtd/spi/sf_probe.c
+++ b/drivers/mtd/spi/sf_probe.c
@@ -99,6 +99,37 @@
 	}
 }
 
+#ifdef CONFIG_SPI_FLASH_BAR
+static int spi_flash_read_bank(struct spi_flash *flash, u8 idcode0)
+{
+	u8 curr_bank = 0;
+	int ret;
+
+	if (flash->size <= SPI_FLASH_16MB_BOUN)
+		goto bank_end;
+
+	switch (idcode0) {
+	case SPI_FLASH_CFI_MFR_SPANSION:
+		flash->bank_read_cmd = CMD_BANKADDR_BRRD;
+		flash->bank_write_cmd = CMD_BANKADDR_BRWR;
+	default:
+		flash->bank_read_cmd = CMD_EXTNADDR_RDEAR;
+		flash->bank_write_cmd = CMD_EXTNADDR_WREAR;
+	}
+
+	ret = spi_flash_read_common(flash, &flash->bank_read_cmd, 1,
+				    &curr_bank, 1);
+	if (ret) {
+		debug("SF: fail to read bank addr register\n");
+		return ret;
+	}
+
+bank_end:
+	flash->bank_curr = curr_bank;
+	return 0;
+}
+#endif
+
 static int spi_flash_validate_params(struct spi_slave *spi, u8 *idcode,
 				     struct spi_flash *flash)
 {
@@ -132,15 +163,15 @@
 	flash->name = params->name;
 	flash->memory_map = spi->memory_map;
 	flash->dual_flash = flash->spi->option;
-#ifdef CONFIG_DM_SPI_FLASH
-	flash->flags = params->flags;
-#endif
 
 	/* Assign spi_flash ops */
 #ifndef CONFIG_DM_SPI_FLASH
 	flash->write = spi_flash_cmd_write_ops;
 #if defined(CONFIG_SPI_FLASH_SST)
-	if (params->flags & SST_WR) {
+	if (params->flags & SST_WR)
+		flash->flags |= SNOR_F_SST_WR;
+
+	if (params->flags & SNOR_F_SST_WR) {
 		if (flash->spi->op_mode_tx & SPI_OPM_TX_BP)
 			flash->write = sst_write_bp;
 		else
@@ -226,34 +257,16 @@
 		flash->dummy_byte = 1;
 	}
 
-	/* Poll cmd selection */
-	flash->poll_cmd = CMD_READ_STATUS;
 #ifdef CONFIG_SPI_FLASH_STMICRO
 	if (params->flags & E_FSR)
-		flash->poll_cmd = CMD_FLAG_STATUS;
+		flash->flags |= SNOR_F_USE_FSR;
 #endif
 
 	/* Configure the BAR - discover bank cmds and read current bank */
 #ifdef CONFIG_SPI_FLASH_BAR
-	u8 curr_bank = 0;
-	if (flash->size > SPI_FLASH_16MB_BOUN) {
-		int ret;
-
-		flash->bank_read_cmd = (idcode[0] == 0x01) ?
-					CMD_BANKADDR_BRRD : CMD_EXTNADDR_RDEAR;
-		flash->bank_write_cmd = (idcode[0] == 0x01) ?
-					CMD_BANKADDR_BRWR : CMD_EXTNADDR_WREAR;
-
-		ret = spi_flash_read_common(flash, &flash->bank_read_cmd, 1,
-					    &curr_bank, 1);
-		if (ret) {
-			debug("SF: fail to read bank addr register\n");
-			return ret;
-		}
-		flash->bank_curr = curr_bank;
-	} else {
-		flash->bank_curr = curr_bank;
-	}
+	int ret = spi_flash_read_bank(flash, idcode[0]);
+	if (ret < 0)
+		return ret;
 #endif
 
 	/* Flash powers up read-only, so clear BP# bits */
@@ -451,7 +464,7 @@
 	struct spi_flash *flash = dev_get_uclass_priv(dev);
 
 #if defined(CONFIG_SPI_FLASH_SST)
-	if (flash->flags & SST_WR) {
+	if (flash->flags & SNOR_F_SST_WR) {
 		if (flash->spi->op_mode_tx & SPI_OPM_TX_BP)
 			return sst_write_bp(flash, offset, len, buf);
 		else
@@ -471,7 +484,7 @@
 
 int spi_flash_std_probe(struct udevice *dev)
 {
-	struct spi_slave *slave = dev_get_parentdata(dev);
+	struct spi_slave *slave = dev_get_parent_priv(dev);
 	struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev);
 	struct spi_flash *flash;
 
diff --git a/drivers/mtd/ubi/attach.c b/drivers/mtd/ubi/attach.c
index 1bdbfa7..90fb74a 100644
--- a/drivers/mtd/ubi/attach.c
+++ b/drivers/mtd/ubi/attach.c
@@ -172,6 +172,7 @@
 
 /**
  * validate_vid_hdr - check volume identifier header.
+ * @ubi: UBI device description object
  * @vid_hdr: the volume identifier header to check
  * @av: information about the volume this logical eraseblock belongs to
  * @pnum: physical eraseblock number the VID header came from
@@ -184,7 +185,8 @@
  * information in the VID header is consistent to the information in other VID
  * headers of the same volume.
  */
-static int validate_vid_hdr(const struct ubi_vid_hdr *vid_hdr,
+static int validate_vid_hdr(const struct ubi_device *ubi,
+			    const struct ubi_vid_hdr *vid_hdr,
 			    const struct ubi_ainf_volume *av, int pnum)
 {
 	int vol_type = vid_hdr->vol_type;
@@ -202,7 +204,7 @@
 		 */
 
 		if (vol_id != av->vol_id) {
-			ubi_err("inconsistent vol_id");
+			ubi_err(ubi, "inconsistent vol_id");
 			goto bad;
 		}
 
@@ -212,17 +214,17 @@
 			av_vol_type = UBI_VID_DYNAMIC;
 
 		if (vol_type != av_vol_type) {
-			ubi_err("inconsistent vol_type");
+			ubi_err(ubi, "inconsistent vol_type");
 			goto bad;
 		}
 
 		if (used_ebs != av->used_ebs) {
-			ubi_err("inconsistent used_ebs");
+			ubi_err(ubi, "inconsistent used_ebs");
 			goto bad;
 		}
 
 		if (data_pad != av->data_pad) {
-			ubi_err("inconsistent data_pad");
+			ubi_err(ubi, "inconsistent data_pad");
 			goto bad;
 		}
 	}
@@ -230,7 +232,7 @@
 	return 0;
 
 bad:
-	ubi_err("inconsistent VID header at PEB %d", pnum);
+	ubi_err(ubi, "inconsistent VID header at PEB %d", pnum);
 	ubi_dump_vid_hdr(vid_hdr);
 	ubi_dump_av(av);
 	return -EINVAL;
@@ -332,7 +334,7 @@
 		 * support these images anymore. Well, those images still work,
 		 * but only if no unclean reboots happened.
 		 */
-		ubi_err("unsupported on-flash UBI format");
+		ubi_err(ubi, "unsupported on-flash UBI format");
 		return -EINVAL;
 	}
 
@@ -373,7 +375,7 @@
 			if (err == UBI_IO_BITFLIPS)
 				bitflips = 1;
 			else {
-				ubi_err("VID of PEB %d header is bad, but it was OK earlier, err %d",
+				ubi_err(ubi, "VID of PEB %d header is bad, but it was OK earlier, err %d",
 					pnum, err);
 				if (err > 0)
 					err = -EIO;
@@ -404,7 +406,7 @@
 		second_is_newer = !second_is_newer;
 	} else {
 		dbg_bld("PEB %d CRC is OK", pnum);
-		bitflips = !!err;
+		bitflips |= !!err;
 	}
 	mutex_unlock(&ubi->buf_mutex);
 
@@ -503,7 +505,7 @@
 		 * logical eraseblocks because there was an unclean reboot.
 		 */
 		if (aeb->sqnum == sqnum && sqnum != 0) {
-			ubi_err("two LEBs with same sequence number %llu",
+			ubi_err(ubi, "two LEBs with same sequence number %llu",
 				sqnum);
 			ubi_dump_aeb(aeb, 0);
 			ubi_dump_vid_hdr(vid_hdr);
@@ -523,7 +525,7 @@
 			 * This logical eraseblock is newer than the one
 			 * found earlier.
 			 */
-			err = validate_vid_hdr(vid_hdr, av, pnum);
+			err = validate_vid_hdr(ubi, vid_hdr, av, pnum);
 			if (err)
 				return err;
 
@@ -561,7 +563,7 @@
 	 * attaching information.
 	 */
 
-	err = validate_vid_hdr(vid_hdr, av, pnum);
+	err = validate_vid_hdr(ubi, vid_hdr, av, pnum);
 	if (err)
 		return err;
 
@@ -664,7 +666,8 @@
 		 * Erase counter overflow. Upgrade UBI and use 64-bit
 		 * erase counters internally.
 		 */
-		ubi_err("erase counter overflow at PEB %d, EC %d", pnum, ec);
+		ubi_err(ubi, "erase counter overflow at PEB %d, EC %d",
+			pnum, ec);
 		return -EINVAL;
 	}
 
@@ -732,7 +735,7 @@
 		return aeb;
 	}
 
-	ubi_err("no free eraseblocks");
+	ubi_err(ubi, "no free eraseblocks");
 	return ERR_PTR(-ENOSPC);
 }
 
@@ -781,9 +784,9 @@
 	if (ubi_check_pattern(ubi->peb_buf, 0xFF, ubi->leb_size))
 		goto out_unlock;
 
-	ubi_err("PEB %d contains corrupted VID header, and the data does not contain all 0xFF",
+	ubi_err(ubi, "PEB %d contains corrupted VID header, and the data does not contain all 0xFF",
 		pnum);
-	ubi_err("this may be a non-UBI PEB or a severe VID header corruption which requires manual inspection");
+	ubi_err(ubi, "this may be a non-UBI PEB or a severe VID header corruption which requires manual inspection");
 	ubi_dump_vid_hdr(vid_hdr);
 	pr_err("hexdump of PEB %d offset %d, length %d",
 	       pnum, ubi->leb_start, ubi->leb_size);
@@ -855,7 +858,8 @@
 		bitflips = 1;
 		break;
 	default:
-		ubi_err("'ubi_io_read_ec_hdr()' returned unknown code %d", err);
+		ubi_err(ubi, "'ubi_io_read_ec_hdr()' returned unknown code %d",
+			err);
 		return -EINVAL;
 	}
 
@@ -864,7 +868,7 @@
 
 		/* Make sure UBI version is OK */
 		if (ech->version != UBI_VERSION) {
-			ubi_err("this UBI version is %d, image version is %d",
+			ubi_err(ubi, "this UBI version is %d, image version is %d",
 				UBI_VERSION, (int)ech->version);
 			return -EINVAL;
 		}
@@ -878,7 +882,7 @@
 			 * flash. Upgrade UBI and use 64-bit erase counters
 			 * internally.
 			 */
-			ubi_err("erase counter overflow, max is %d",
+			ubi_err(ubi, "erase counter overflow, max is %d",
 				UBI_MAX_ERASECOUNTER);
 			ubi_dump_ec_hdr(ech);
 			return -EINVAL;
@@ -899,7 +903,7 @@
 		if (!ubi->image_seq)
 			ubi->image_seq = image_seq;
 		if (image_seq && ubi->image_seq != image_seq) {
-			ubi_err("bad image sequence number %d in PEB %d, expected %d",
+			ubi_err(ubi, "bad image sequence number %d in PEB %d, expected %d",
 				image_seq, pnum, ubi->image_seq);
 			ubi_dump_ec_hdr(ech);
 			return -EINVAL;
@@ -977,7 +981,7 @@
 			return err;
 		goto adjust_mean_ec;
 	default:
-		ubi_err("'ubi_io_read_vid_hdr()' returned unknown code %d",
+		ubi_err(ubi, "'ubi_io_read_vid_hdr()' returned unknown code %d",
 			err);
 		return -EINVAL;
 	}
@@ -995,7 +999,7 @@
 		case UBI_COMPAT_DELETE:
 			if (vol_id != UBI_FM_SB_VOLUME_ID
 			    && vol_id != UBI_FM_DATA_VOLUME_ID) {
-				ubi_msg("\"delete\" compatible internal volume %d:%d found, will remove it",
+				ubi_msg(ubi, "\"delete\" compatible internal volume %d:%d found, will remove it",
 					vol_id, lnum);
 			}
 			err = add_to_list(ai, pnum, vol_id, lnum,
@@ -1005,13 +1009,13 @@
 			return 0;
 
 		case UBI_COMPAT_RO:
-			ubi_msg("read-only compatible internal volume %d:%d found, switch to read-only mode",
+			ubi_msg(ubi, "read-only compatible internal volume %d:%d found, switch to read-only mode",
 				vol_id, lnum);
 			ubi->ro_mode = 1;
 			break;
 
 		case UBI_COMPAT_PRESERVE:
-			ubi_msg("\"preserve\" compatible internal volume %d:%d found",
+			ubi_msg(ubi, "\"preserve\" compatible internal volume %d:%d found",
 				vol_id, lnum);
 			err = add_to_list(ai, pnum, vol_id, lnum,
 					  ec, 0, &ai->alien);
@@ -1020,14 +1024,14 @@
 			return 0;
 
 		case UBI_COMPAT_REJECT:
-			ubi_err("incompatible internal volume %d:%d found",
+			ubi_err(ubi, "incompatible internal volume %d:%d found",
 				vol_id, lnum);
 			return -EINVAL;
 		}
 	}
 
 	if (ec_err)
-		ubi_warn("valid VID header but corrupted EC header at PEB %d",
+		ubi_warn(ubi, "valid VID header but corrupted EC header at PEB %d",
 			 pnum);
 	err = ubi_add_to_av(ubi, ai, pnum, ec, vidh, bitflips);
 	if (err)
@@ -1071,7 +1075,7 @@
 	 * with the flash HW or driver.
 	 */
 	if (ai->corr_peb_count) {
-		ubi_err("%d PEBs are corrupted and preserved",
+		ubi_err(ubi, "%d PEBs are corrupted and preserved",
 			ai->corr_peb_count);
 		pr_err("Corrupted PEBs are:");
 		list_for_each_entry(aeb, &ai->corr, u.list)
@@ -1083,7 +1087,7 @@
 		 * otherwise, only print a warning.
 		 */
 		if (ai->corr_peb_count >= max_corr) {
-			ubi_err("too many corrupted PEBs, refusing");
+			ubi_err(ubi, "too many corrupted PEBs, refusing");
 			return -EINVAL;
 		}
 	}
@@ -1106,11 +1110,11 @@
 		 */
 		if (ai->maybe_bad_peb_count <= 2) {
 			ai->is_empty = 1;
-			ubi_msg("empty MTD device detected");
+			ubi_msg(ubi, "empty MTD device detected");
 			get_random_bytes(&ubi->image_seq,
 					 sizeof(ubi->image_seq));
 		} else {
-			ubi_err("MTD device is not UBI-formatted and possibly contains non-UBI data - refusing it");
+			ubi_err(ubi, "MTD device is not UBI-formatted and possibly contains non-UBI data - refusing it");
 			return -EINVAL;
 		}
 
@@ -1244,7 +1248,7 @@
 			goto out_vidh;
 	}
 
-	ubi_msg("scanning is finished");
+	ubi_msg(ubi, "scanning is finished");
 
 	/* Calculate mean erase counter */
 	if (ai->ec_count)
@@ -1293,6 +1297,30 @@
 	return err;
 }
 
+static struct ubi_attach_info *alloc_ai(void)
+{
+	struct ubi_attach_info *ai;
+
+	ai = kzalloc(sizeof(struct ubi_attach_info), GFP_KERNEL);
+	if (!ai)
+		return ai;
+
+	INIT_LIST_HEAD(&ai->corr);
+	INIT_LIST_HEAD(&ai->free);
+	INIT_LIST_HEAD(&ai->erase);
+	INIT_LIST_HEAD(&ai->alien);
+	ai->volumes = RB_ROOT;
+	ai->aeb_slab_cache = kmem_cache_create("ubi_aeb_slab_cache",
+					       sizeof(struct ubi_ainf_peb),
+					       0, 0, NULL);
+	if (!ai->aeb_slab_cache) {
+		kfree(ai);
+		ai = NULL;
+	}
+
+	return ai;
+}
+
 #ifdef CONFIG_MTD_UBI_FASTMAP
 
 /**
@@ -1305,7 +1333,7 @@
  * UBI_NO_FASTMAP denotes that no fastmap was found.
  * UBI_BAD_FASTMAP denotes that the found fastmap was invalid.
  */
-static int scan_fast(struct ubi_device *ubi, struct ubi_attach_info *ai)
+static int scan_fast(struct ubi_device *ubi, struct ubi_attach_info **ai)
 {
 	int err, pnum, fm_anchor = -1;
 	unsigned long long max_sqnum = 0;
@@ -1326,7 +1354,7 @@
 		cond_resched();
 
 		dbg_gen("process PEB %d", pnum);
-		err = scan_peb(ubi, ai, pnum, &vol_id, &sqnum);
+		err = scan_peb(ubi, *ai, pnum, &vol_id, &sqnum);
 		if (err < 0)
 			goto out_vidh;
 
@@ -1342,7 +1370,12 @@
 	if (fm_anchor < 0)
 		return UBI_NO_FASTMAP;
 
-	return ubi_scan_fastmap(ubi, ai, fm_anchor);
+	destroy_ai(*ai);
+	*ai = alloc_ai();
+	if (!*ai)
+		return -ENOMEM;
+
+	return ubi_scan_fastmap(ubi, *ai, fm_anchor);
 
 out_vidh:
 	ubi_free_vid_hdr(ubi, vidh);
@@ -1354,30 +1387,6 @@
 
 #endif
 
-static struct ubi_attach_info *alloc_ai(const char *slab_name)
-{
-	struct ubi_attach_info *ai;
-
-	ai = kzalloc(sizeof(struct ubi_attach_info), GFP_KERNEL);
-	if (!ai)
-		return ai;
-
-	INIT_LIST_HEAD(&ai->corr);
-	INIT_LIST_HEAD(&ai->free);
-	INIT_LIST_HEAD(&ai->erase);
-	INIT_LIST_HEAD(&ai->alien);
-	ai->volumes = RB_ROOT;
-	ai->aeb_slab_cache = kmem_cache_create(slab_name,
-					       sizeof(struct ubi_ainf_peb),
-					       0, 0, NULL);
-	if (!ai->aeb_slab_cache) {
-		kfree(ai);
-		ai = NULL;
-	}
-
-	return ai;
-}
-
 /**
  * ubi_attach - attach an MTD device.
  * @ubi: UBI device descriptor
@@ -1391,7 +1400,7 @@
 	int err;
 	struct ubi_attach_info *ai;
 
-	ai = alloc_ai("ubi_aeb_slab_cache");
+	ai = alloc_ai();
 	if (!ai)
 		return -ENOMEM;
 
@@ -1405,11 +1414,11 @@
 	if (force_scan)
 		err = scan_all(ubi, ai, 0);
 	else {
-		err = scan_fast(ubi, ai);
-		if (err > 0) {
+		err = scan_fast(ubi, &ai);
+		if (err > 0 || mtd_is_eccerr(err)) {
 			if (err != UBI_NO_FASTMAP) {
 				destroy_ai(ai);
-				ai = alloc_ai("ubi_aeb_slab_cache2");
+				ai = alloc_ai();
 				if (!ai)
 					return -ENOMEM;
 
@@ -1445,10 +1454,10 @@
 		goto out_wl;
 
 #ifdef CONFIG_MTD_UBI_FASTMAP
-	if (ubi->fm && ubi_dbg_chk_gen(ubi)) {
+	if (ubi->fm && ubi_dbg_chk_fastmap(ubi)) {
 		struct ubi_attach_info *scan_ai;
 
-		scan_ai = alloc_ai("ubi_ckh_aeb_slab_cache");
+		scan_ai = alloc_ai();
 		if (!scan_ai) {
 			err = -ENOMEM;
 			goto out_wl;
@@ -1511,37 +1520,37 @@
 		vols_found += 1;
 
 		if (ai->is_empty) {
-			ubi_err("bad is_empty flag");
+			ubi_err(ubi, "bad is_empty flag");
 			goto bad_av;
 		}
 
 		if (av->vol_id < 0 || av->highest_lnum < 0 ||
 		    av->leb_count < 0 || av->vol_type < 0 || av->used_ebs < 0 ||
 		    av->data_pad < 0 || av->last_data_size < 0) {
-			ubi_err("negative values");
+			ubi_err(ubi, "negative values");
 			goto bad_av;
 		}
 
 		if (av->vol_id >= UBI_MAX_VOLUMES &&
 		    av->vol_id < UBI_INTERNAL_VOL_START) {
-			ubi_err("bad vol_id");
+			ubi_err(ubi, "bad vol_id");
 			goto bad_av;
 		}
 
 		if (av->vol_id > ai->highest_vol_id) {
-			ubi_err("highest_vol_id is %d, but vol_id %d is there",
+			ubi_err(ubi, "highest_vol_id is %d, but vol_id %d is there",
 				ai->highest_vol_id, av->vol_id);
 			goto out;
 		}
 
 		if (av->vol_type != UBI_DYNAMIC_VOLUME &&
 		    av->vol_type != UBI_STATIC_VOLUME) {
-			ubi_err("bad vol_type");
+			ubi_err(ubi, "bad vol_type");
 			goto bad_av;
 		}
 
 		if (av->data_pad > ubi->leb_size / 2) {
-			ubi_err("bad data_pad");
+			ubi_err(ubi, "bad data_pad");
 			goto bad_av;
 		}
 
@@ -1553,48 +1562,48 @@
 			leb_count += 1;
 
 			if (aeb->pnum < 0 || aeb->ec < 0) {
-				ubi_err("negative values");
+				ubi_err(ubi, "negative values");
 				goto bad_aeb;
 			}
 
 			if (aeb->ec < ai->min_ec) {
-				ubi_err("bad ai->min_ec (%d), %d found",
+				ubi_err(ubi, "bad ai->min_ec (%d), %d found",
 					ai->min_ec, aeb->ec);
 				goto bad_aeb;
 			}
 
 			if (aeb->ec > ai->max_ec) {
-				ubi_err("bad ai->max_ec (%d), %d found",
+				ubi_err(ubi, "bad ai->max_ec (%d), %d found",
 					ai->max_ec, aeb->ec);
 				goto bad_aeb;
 			}
 
 			if (aeb->pnum >= ubi->peb_count) {
-				ubi_err("too high PEB number %d, total PEBs %d",
+				ubi_err(ubi, "too high PEB number %d, total PEBs %d",
 					aeb->pnum, ubi->peb_count);
 				goto bad_aeb;
 			}
 
 			if (av->vol_type == UBI_STATIC_VOLUME) {
 				if (aeb->lnum >= av->used_ebs) {
-					ubi_err("bad lnum or used_ebs");
+					ubi_err(ubi, "bad lnum or used_ebs");
 					goto bad_aeb;
 				}
 			} else {
 				if (av->used_ebs != 0) {
-					ubi_err("non-zero used_ebs");
+					ubi_err(ubi, "non-zero used_ebs");
 					goto bad_aeb;
 				}
 			}
 
 			if (aeb->lnum > av->highest_lnum) {
-				ubi_err("incorrect highest_lnum or lnum");
+				ubi_err(ubi, "incorrect highest_lnum or lnum");
 				goto bad_aeb;
 			}
 		}
 
 		if (av->leb_count != leb_count) {
-			ubi_err("bad leb_count, %d objects in the tree",
+			ubi_err(ubi, "bad leb_count, %d objects in the tree",
 				leb_count);
 			goto bad_av;
 		}
@@ -1605,13 +1614,13 @@
 		aeb = last_aeb;
 
 		if (aeb->lnum != av->highest_lnum) {
-			ubi_err("bad highest_lnum");
+			ubi_err(ubi, "bad highest_lnum");
 			goto bad_aeb;
 		}
 	}
 
 	if (vols_found != ai->vols_found) {
-		ubi_err("bad ai->vols_found %d, should be %d",
+		ubi_err(ubi, "bad ai->vols_found %d, should be %d",
 			ai->vols_found, vols_found);
 		goto out;
 	}
@@ -1628,7 +1637,8 @@
 
 			err = ubi_io_read_vid_hdr(ubi, aeb->pnum, vidh, 1);
 			if (err && err != UBI_IO_BITFLIPS) {
-				ubi_err("VID header is not OK (%d)", err);
+				ubi_err(ubi, "VID header is not OK (%d)",
+					err);
 				if (err > 0)
 					err = -EIO;
 				return err;
@@ -1637,37 +1647,37 @@
 			vol_type = vidh->vol_type == UBI_VID_DYNAMIC ?
 				   UBI_DYNAMIC_VOLUME : UBI_STATIC_VOLUME;
 			if (av->vol_type != vol_type) {
-				ubi_err("bad vol_type");
+				ubi_err(ubi, "bad vol_type");
 				goto bad_vid_hdr;
 			}
 
 			if (aeb->sqnum != be64_to_cpu(vidh->sqnum)) {
-				ubi_err("bad sqnum %llu", aeb->sqnum);
+				ubi_err(ubi, "bad sqnum %llu", aeb->sqnum);
 				goto bad_vid_hdr;
 			}
 
 			if (av->vol_id != be32_to_cpu(vidh->vol_id)) {
-				ubi_err("bad vol_id %d", av->vol_id);
+				ubi_err(ubi, "bad vol_id %d", av->vol_id);
 				goto bad_vid_hdr;
 			}
 
 			if (av->compat != vidh->compat) {
-				ubi_err("bad compat %d", vidh->compat);
+				ubi_err(ubi, "bad compat %d", vidh->compat);
 				goto bad_vid_hdr;
 			}
 
 			if (aeb->lnum != be32_to_cpu(vidh->lnum)) {
-				ubi_err("bad lnum %d", aeb->lnum);
+				ubi_err(ubi, "bad lnum %d", aeb->lnum);
 				goto bad_vid_hdr;
 			}
 
 			if (av->used_ebs != be32_to_cpu(vidh->used_ebs)) {
-				ubi_err("bad used_ebs %d", av->used_ebs);
+				ubi_err(ubi, "bad used_ebs %d", av->used_ebs);
 				goto bad_vid_hdr;
 			}
 
 			if (av->data_pad != be32_to_cpu(vidh->data_pad)) {
-				ubi_err("bad data_pad %d", av->data_pad);
+				ubi_err(ubi, "bad data_pad %d", av->data_pad);
 				goto bad_vid_hdr;
 			}
 		}
@@ -1676,12 +1686,13 @@
 			continue;
 
 		if (av->highest_lnum != be32_to_cpu(vidh->lnum)) {
-			ubi_err("bad highest_lnum %d", av->highest_lnum);
+			ubi_err(ubi, "bad highest_lnum %d", av->highest_lnum);
 			goto bad_vid_hdr;
 		}
 
 		if (av->last_data_size != be32_to_cpu(vidh->data_size)) {
-			ubi_err("bad last_data_size %d", av->last_data_size);
+			ubi_err(ubi, "bad last_data_size %d",
+				av->last_data_size);
 			goto bad_vid_hdr;
 		}
 	}
@@ -1722,7 +1733,7 @@
 	err = 0;
 	for (pnum = 0; pnum < ubi->peb_count; pnum++)
 		if (!buf[pnum]) {
-			ubi_err("PEB %d is not referred", pnum);
+			ubi_err(ubi, "PEB %d is not referred", pnum);
 			err = 1;
 		}
 
@@ -1732,18 +1743,18 @@
 	return 0;
 
 bad_aeb:
-	ubi_err("bad attaching information about LEB %d", aeb->lnum);
+	ubi_err(ubi, "bad attaching information about LEB %d", aeb->lnum);
 	ubi_dump_aeb(aeb, 0);
 	ubi_dump_av(av);
 	goto out;
 
 bad_av:
-	ubi_err("bad attaching information about volume %d", av->vol_id);
+	ubi_err(ubi, "bad attaching information about volume %d", av->vol_id);
 	ubi_dump_av(av);
 	goto out;
 
 bad_vid_hdr:
-	ubi_err("bad attaching information about volume %d", av->vol_id);
+	ubi_err(ubi, "bad attaching information about volume %d", av->vol_id);
 	ubi_dump_av(av);
 	ubi_dump_vid_hdr(vidh);
 
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index 290d524..f0a3b67 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -80,6 +80,7 @@
 #ifdef CONFIG_MTD_UBI_FASTMAP
 /* UBI module parameter to enable fastmap automatically on non-fastmap images */
 static bool fm_autoconvert;
+static bool fm_debug;
 #endif
 #else
 #ifdef CONFIG_MTD_UBI_FASTMAP
@@ -87,10 +88,12 @@
 #define CONFIG_MTD_UBI_FASTMAP_AUTOCONVERT 0
 #endif
 static bool fm_autoconvert = CONFIG_MTD_UBI_FASTMAP_AUTOCONVERT;
+#if !defined(CONFIG_MTD_UBI_FM_DEBUG)
+#define CONFIG_MTD_UBI_FM_DEBUG 0
 #endif
+static bool fm_debug = CONFIG_MTD_UBI_FM_DEBUG;
 #endif
-/* Root UBI "class" object (corresponds to '/<sysfs>/class/ubi/') */
-struct class *ubi_class;
+#endif
 
 /* Slab cache for wear-leveling entries */
 struct kmem_cache *ubi_wl_entry_slab;
@@ -110,7 +113,7 @@
 #else
 struct ubi_device *ubi_devices[UBI_MAX_DEVICES];
 #endif
-
+ 
 #ifndef __UBOOT__
 /* Serializes UBI devices creations and removals */
 DEFINE_MUTEX(ubi_devices_mutex);
@@ -126,8 +129,17 @@
 }
 
 /* UBI version attribute ('/<sysfs>/class/ubi/version') */
-static struct class_attribute ubi_version =
-	__ATTR(version, S_IRUGO, ubi_version_show, NULL);
+static struct class_attribute ubi_class_attrs[] = {
+	__ATTR(version, S_IRUGO, ubi_version_show, NULL),
+	__ATTR_NULL
+};
+
+/* Root UBI "class" object (corresponds to '/<sysfs>/class/ubi/') */
+struct class ubi_class = {
+	.name		= UBI_NAME_STR,
+	.owner		= THIS_MODULE,
+	.class_attrs	= ubi_class_attrs,
+};
 
 static ssize_t dev_attribute_show(struct device *dev,
 				  struct device_attribute *attr, char *buf);
@@ -169,23 +181,22 @@
  */
 int ubi_volume_notify(struct ubi_device *ubi, struct ubi_volume *vol, int ntype)
 {
+	int ret;
 	struct ubi_notification nt;
 
 	ubi_do_get_device_info(ubi, &nt.di);
 	ubi_do_get_volume_info(ubi, vol, &nt.vi);
 
-#ifdef CONFIG_MTD_UBI_FASTMAP
 	switch (ntype) {
 	case UBI_VOLUME_ADDED:
 	case UBI_VOLUME_REMOVED:
 	case UBI_VOLUME_RESIZED:
 	case UBI_VOLUME_RENAMED:
-		if (ubi_update_fastmap(ubi)) {
-			ubi_err("Unable to update fastmap!");
-			ubi_ro_mode(ubi);
-		}
+		ret = ubi_update_fastmap(ubi);
+		if (ret)
+			ubi_msg(ubi, "Unable to write a new fastmap: %i", ret);
 	}
-#endif
+
 	return blocking_notifier_call_chain(&ubi_notifiers, ntype, &nt);
 }
 
@@ -406,6 +417,22 @@
 	return ret;
 }
 
+static struct attribute *ubi_dev_attrs[] = {
+	&dev_eraseblock_size.attr,
+	&dev_avail_eraseblocks.attr,
+	&dev_total_eraseblocks.attr,
+	&dev_volumes_count.attr,
+	&dev_max_ec.attr,
+	&dev_reserved_for_bad.attr,
+	&dev_bad_peb_count.attr,
+	&dev_max_vol_count.attr,
+	&dev_min_io_size.attr,
+	&dev_bgt_enabled.attr,
+	&dev_mtd_num.attr,
+	NULL
+};
+ATTRIBUTE_GROUPS(ubi_dev);
+
 static void dev_release(struct device *dev)
 {
 	struct ubi_device *ubi = container_of(dev, struct ubi_device, dev);
@@ -428,45 +455,15 @@
 
 	ubi->dev.release = dev_release;
 	ubi->dev.devt = ubi->cdev.dev;
-	ubi->dev.class = ubi_class;
+	ubi->dev.class = &ubi_class;
+	ubi->dev.groups = ubi_dev_groups;
 	dev_set_name(&ubi->dev, UBI_NAME_STR"%d", ubi->ubi_num);
 	err = device_register(&ubi->dev);
 	if (err)
 		return err;
 
 	*ref = 1;
-	err = device_create_file(&ubi->dev, &dev_eraseblock_size);
-	if (err)
-		return err;
-	err = device_create_file(&ubi->dev, &dev_avail_eraseblocks);
-	if (err)
-		return err;
-	err = device_create_file(&ubi->dev, &dev_total_eraseblocks);
-	if (err)
-		return err;
-	err = device_create_file(&ubi->dev, &dev_volumes_count);
-	if (err)
-		return err;
-	err = device_create_file(&ubi->dev, &dev_max_ec);
-	if (err)
-		return err;
-	err = device_create_file(&ubi->dev, &dev_reserved_for_bad);
-	if (err)
-		return err;
-	err = device_create_file(&ubi->dev, &dev_bad_peb_count);
-	if (err)
-		return err;
-	err = device_create_file(&ubi->dev, &dev_max_vol_count);
-	if (err)
-		return err;
-	err = device_create_file(&ubi->dev, &dev_min_io_size);
-	if (err)
-		return err;
-	err = device_create_file(&ubi->dev, &dev_bgt_enabled);
-	if (err)
-		return err;
-	err = device_create_file(&ubi->dev, &dev_mtd_num);
-	return err;
+	return 0;
 }
 
 /**
@@ -475,17 +472,6 @@
  */
 static void ubi_sysfs_close(struct ubi_device *ubi)
 {
-	device_remove_file(&ubi->dev, &dev_mtd_num);
-	device_remove_file(&ubi->dev, &dev_bgt_enabled);
-	device_remove_file(&ubi->dev, &dev_min_io_size);
-	device_remove_file(&ubi->dev, &dev_max_vol_count);
-	device_remove_file(&ubi->dev, &dev_bad_peb_count);
-	device_remove_file(&ubi->dev, &dev_reserved_for_bad);
-	device_remove_file(&ubi->dev, &dev_max_ec);
-	device_remove_file(&ubi->dev, &dev_volumes_count);
-	device_remove_file(&ubi->dev, &dev_total_eraseblocks);
-	device_remove_file(&ubi->dev, &dev_avail_eraseblocks);
-	device_remove_file(&ubi->dev, &dev_eraseblock_size);
 	device_unregister(&ubi->dev);
 }
 #endif
@@ -541,7 +527,7 @@
 	 */
 	err = alloc_chrdev_region(&dev, 0, ubi->vtbl_slots + 1, ubi->ubi_name);
 	if (err) {
-		ubi_err("cannot register UBI character devices");
+		ubi_err(ubi, "cannot register UBI character devices");
 		return err;
 	}
 
@@ -552,7 +538,7 @@
 
 	err = cdev_add(&ubi->cdev, dev, 1);
 	if (err) {
-		ubi_err("cannot add character device");
+		ubi_err(ubi, "cannot add character device");
 		goto out_unreg;
 	}
 
@@ -564,7 +550,7 @@
 		if (ubi->volumes[i]) {
 			err = ubi_add_volume(ubi, ubi->volumes[i]);
 			if (err) {
-				ubi_err("cannot add volume %d", i);
+				ubi_err(ubi, "cannot add volume %d", i);
 				goto out_volumes;
 			}
 		}
@@ -580,7 +566,8 @@
 	cdev_del(&ubi->cdev);
 out_unreg:
 	unregister_chrdev_region(ubi->cdev.dev, ubi->vtbl_slots + 1);
-	ubi_err("cannot initialize UBI %s, error %d", ubi->ubi_name, err);
+	ubi_err(ubi, "cannot initialize UBI %s, error %d",
+		ubi->ubi_name, err);
 	return err;
 }
 
@@ -674,7 +661,7 @@
 		 * guess we should just pick the largest region. But this is
 		 * not implemented.
 		 */
-		ubi_err("multiple regions, not implemented");
+		ubi_err(ubi, "multiple regions, not implemented");
 		return -EINVAL;
 	}
 
@@ -709,7 +696,7 @@
 	 * which allows us to avoid costly division operations.
 	 */
 	if (!is_power_of_2(ubi->min_io_size)) {
-		ubi_err("min. I/O unit (%d) is not power of 2",
+		ubi_err(ubi, "min. I/O unit (%d) is not power of 2",
 			ubi->min_io_size);
 		return -EINVAL;
 	}
@@ -726,7 +713,7 @@
 	if (ubi->max_write_size < ubi->min_io_size ||
 	    ubi->max_write_size % ubi->min_io_size ||
 	    !is_power_of_2(ubi->max_write_size)) {
-		ubi_err("bad write buffer size %d for %d min. I/O unit",
+		ubi_err(ubi, "bad write buffer size %d for %d min. I/O unit",
 			ubi->max_write_size, ubi->min_io_size);
 		return -EINVAL;
 	}
@@ -763,7 +750,7 @@
 
 	/* The shift must be aligned to 32-bit boundary */
 	if (ubi->vid_hdr_shift % 4) {
-		ubi_err("unaligned VID header shift %d",
+		ubi_err(ubi, "unaligned VID header shift %d",
 			ubi->vid_hdr_shift);
 		return -EINVAL;
 	}
@@ -773,7 +760,7 @@
 	    ubi->leb_start < ubi->vid_hdr_offset + UBI_VID_HDR_SIZE ||
 	    ubi->leb_start > ubi->peb_size - UBI_VID_HDR_SIZE ||
 	    ubi->leb_start & (ubi->min_io_size - 1)) {
-		ubi_err("bad VID header (%d) or data offsets (%d)",
+		ubi_err(ubi, "bad VID header (%d) or data offsets (%d)",
 			ubi->vid_hdr_offset, ubi->leb_start);
 		return -EINVAL;
 	}
@@ -793,14 +780,14 @@
 	 * read-only mode.
 	 */
 	if (ubi->vid_hdr_offset + UBI_VID_HDR_SIZE <= ubi->hdrs_min_io_size) {
-		ubi_warn("EC and VID headers are in the same minimal I/O unit, switch to read-only mode");
+		ubi_warn(ubi, "EC and VID headers are in the same minimal I/O unit, switch to read-only mode");
 		ubi->ro_mode = 1;
 	}
 
 	ubi->leb_size = ubi->peb_size - ubi->leb_start;
 
 	if (!(ubi->mtd->flags & MTD_WRITEABLE)) {
-		ubi_msg("MTD device %d is write-protected, attach in read-only mode",
+		ubi_msg(ubi, "MTD device %d is write-protected, attach in read-only mode",
 			ubi->mtd->index);
 		ubi->ro_mode = 1;
 	}
@@ -833,7 +820,7 @@
 	int err, old_reserved_pebs = vol->reserved_pebs;
 
 	if (ubi->ro_mode) {
-		ubi_warn("skip auto-resize because of R/O mode");
+		ubi_warn(ubi, "skip auto-resize because of R/O mode");
 		return 0;
 	}
 
@@ -854,21 +841,22 @@
 		vtbl_rec = ubi->vtbl[vol_id];
 		err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec);
 		if (err)
-			ubi_err("cannot clean auto-resize flag for volume %d",
+			ubi_err(ubi, "cannot clean auto-resize flag for volume %d",
 				vol_id);
 	} else {
 		desc.vol = vol;
 		err = ubi_resize_volume(&desc,
 					old_reserved_pebs + ubi->avail_pebs);
 		if (err)
-			ubi_err("cannot auto-resize volume %d", vol_id);
+			ubi_err(ubi, "cannot auto-resize volume %d",
+				vol_id);
 	}
 
 	if (err)
 		return err;
 
-	ubi_msg("volume %d (\"%s\") re-sized from %d to %d LEBs", vol_id,
-		vol->name, old_reserved_pebs, vol->reserved_pebs);
+	ubi_msg(ubi, "volume %d (\"%s\") re-sized from %d to %d LEBs",
+		vol_id, vol->name, old_reserved_pebs, vol->reserved_pebs);
 	return 0;
 }
 
@@ -909,7 +897,7 @@
 	for (i = 0; i < UBI_MAX_DEVICES; i++) {
 		ubi = ubi_devices[i];
 		if (ubi && mtd->index == ubi->mtd->index) {
-			ubi_err("mtd%d is already attached to ubi%d",
+			ubi_err(ubi, "mtd%d is already attached to ubi%d",
 				mtd->index, i);
 			return -EEXIST;
 		}
@@ -924,7 +912,7 @@
 	 * no sense to attach emulated MTD devices, so we prohibit this.
 	 */
 	if (mtd->type == MTD_UBIVOLUME) {
-		ubi_err("refuse attaching mtd%d - it is already emulated on top of UBI",
+		ubi_err(ubi, "refuse attaching mtd%d - it is already emulated on top of UBI",
 			mtd->index);
 		return -EINVAL;
 	}
@@ -935,7 +923,7 @@
 			if (!ubi_devices[ubi_num])
 				break;
 		if (ubi_num == UBI_MAX_DEVICES) {
-			ubi_err("only %d UBI devices may be created",
+			ubi_err(ubi, "only %d UBI devices may be created",
 				UBI_MAX_DEVICES);
 			return -ENFILE;
 		}
@@ -945,7 +933,7 @@
 
 		/* Make sure ubi_num is not busy */
 		if (ubi_devices[ubi_num]) {
-			ubi_err("ubi%d already exists", ubi_num);
+			ubi_err(ubi, "already exists");
 			return -EEXIST;
 		}
 	}
@@ -969,21 +957,24 @@
 	 */
 	ubi->fm_pool.max_size = min(((int)mtd_div_by_eb(ubi->mtd->size,
 		ubi->mtd) / 100) * 5, UBI_FM_MAX_POOL_SIZE);
-	if (ubi->fm_pool.max_size < UBI_FM_MIN_POOL_SIZE)
-		ubi->fm_pool.max_size = UBI_FM_MIN_POOL_SIZE;
+	ubi->fm_pool.max_size = max(ubi->fm_pool.max_size,
+		UBI_FM_MIN_POOL_SIZE);
 
-	ubi->fm_wl_pool.max_size = UBI_FM_WL_POOL_SIZE;
+	ubi->fm_wl_pool.max_size = ubi->fm_pool.max_size / 2;
 	ubi->fm_disabled = !fm_autoconvert;
+	if (fm_debug)
+		ubi_enable_dbg_chk_fastmap(ubi);
 
 	if (!ubi->fm_disabled && (int)mtd_div_by_eb(ubi->mtd->size, ubi->mtd)
 	    <= UBI_FM_MAX_START) {
-		ubi_err("More than %i PEBs are needed for fastmap, sorry.",
+		ubi_err(ubi, "More than %i PEBs are needed for fastmap, sorry.",
 			UBI_FM_MAX_START);
 		ubi->fm_disabled = 1;
 	}
 
-	ubi_msg("default fastmap pool size: %d", ubi->fm_pool.max_size);
-	ubi_msg("default fastmap WL pool size: %d", ubi->fm_wl_pool.max_size);
+	ubi_msg(ubi, "default fastmap pool size: %d", ubi->fm_pool.max_size);
+	ubi_msg(ubi, "default fastmap WL pool size: %d",
+		ubi->fm_wl_pool.max_size);
 #else
 	ubi->fm_disabled = 1;
 #endif
@@ -991,10 +982,10 @@
 	mutex_init(&ubi->ckvol_mutex);
 	mutex_init(&ubi->device_mutex);
 	spin_lock_init(&ubi->volumes_lock);
-	mutex_init(&ubi->fm_mutex);
-	init_rwsem(&ubi->fm_sem);
+	init_rwsem(&ubi->fm_protect);
+	init_rwsem(&ubi->fm_eba_sem);
 
-	ubi_msg("attaching mtd%d to ubi%d", mtd->index, ubi_num);
+	ubi_msg(ubi, "attaching mtd%d", mtd->index);
 
 	err = io_init(ubi, max_beb_per1024);
 	if (err)
@@ -1013,7 +1004,8 @@
 #endif
 	err = ubi_attach(ubi, 0);
 	if (err) {
-		ubi_err("failed to attach mtd%d, error %d", mtd->index, err);
+		ubi_err(ubi, "failed to attach mtd%d, error %d",
+			mtd->index, err);
 		goto out_free;
 	}
 
@@ -1034,28 +1026,28 @@
 	ubi->bgt_thread = kthread_create(ubi_thread, ubi, "%s", ubi->bgt_name);
 	if (IS_ERR(ubi->bgt_thread)) {
 		err = PTR_ERR(ubi->bgt_thread);
-		ubi_err("cannot spawn \"%s\", error %d", ubi->bgt_name,
-			err);
+		ubi_err(ubi, "cannot spawn \"%s\", error %d",
+			ubi->bgt_name, err);
 		goto out_debugfs;
 	}
 
-	ubi_msg("attached mtd%d (name \"%s\", size %llu MiB) to ubi%d",
-		mtd->index, mtd->name, ubi->flash_size >> 20, ubi_num);
-	ubi_msg("PEB size: %d bytes (%d KiB), LEB size: %d bytes",
+	ubi_msg(ubi, "attached mtd%d (name \"%s\", size %llu MiB)",
+		mtd->index, mtd->name, ubi->flash_size >> 20);
+	ubi_msg(ubi, "PEB size: %d bytes (%d KiB), LEB size: %d bytes",
 		ubi->peb_size, ubi->peb_size >> 10, ubi->leb_size);
-	ubi_msg("min./max. I/O unit sizes: %d/%d, sub-page size %d",
+	ubi_msg(ubi, "min./max. I/O unit sizes: %d/%d, sub-page size %d",
 		ubi->min_io_size, ubi->max_write_size, ubi->hdrs_min_io_size);
-	ubi_msg("VID header offset: %d (aligned %d), data offset: %d",
+	ubi_msg(ubi, "VID header offset: %d (aligned %d), data offset: %d",
 		ubi->vid_hdr_offset, ubi->vid_hdr_aloffset, ubi->leb_start);
-	ubi_msg("good PEBs: %d, bad PEBs: %d, corrupted PEBs: %d",
+	ubi_msg(ubi, "good PEBs: %d, bad PEBs: %d, corrupted PEBs: %d",
 		ubi->good_peb_count, ubi->bad_peb_count, ubi->corr_peb_count);
-	ubi_msg("user volume: %d, internal volumes: %d, max. volumes count: %d",
+	ubi_msg(ubi, "user volume: %d, internal volumes: %d, max. volumes count: %d",
 		ubi->vol_count - UBI_INT_VOL_COUNT, UBI_INT_VOL_COUNT,
 		ubi->vtbl_slots);
-	ubi_msg("max/mean erase counter: %d/%d, WL threshold: %d, image sequence number: %u",
+	ubi_msg(ubi, "max/mean erase counter: %d/%d, WL threshold: %d, image sequence number: %u",
 		ubi->max_ec, ubi->mean_ec, CONFIG_MTD_UBI_WL_THRESHOLD,
 		ubi->image_seq);
-	ubi_msg("available PEBs: %d, total reserved PEBs: %d, PEBs reserved for bad PEB handling: %d",
+	ubi_msg(ubi, "available PEBs: %d, total reserved PEBs: %d, PEBs reserved for bad PEB handling: %d",
 		ubi->avail_pebs, ubi->rsvd_pebs, ubi->beb_rsvd_pebs);
 
 	/*
@@ -1064,7 +1056,20 @@
 	 */
 	spin_lock(&ubi->wl_lock);
 	ubi->thread_enabled = 1;
+#ifndef __UBOOT__
 	wake_up_process(ubi->bgt_thread);
+#else
+	/*
+	 * U-Boot special: We have no bgt_thread in U-Boot!
+	 * So just call do_work() here directly.
+	 */
+	err = do_work(ubi);
+	if (err) {
+		ubi_err(ubi, "%s: work failed with error code %d",
+			ubi->bgt_name, err);
+	}
+#endif
+
 	spin_unlock(&ubi->wl_lock);
 
 	ubi_devices[ubi_num] = ubi;
@@ -1124,7 +1129,7 @@
 			return -EBUSY;
 		}
 		/* This may only happen if there is a bug */
-		ubi_err("%s reference count %d, destroy anyway",
+		ubi_err(ubi, "%s reference count %d, destroy anyway",
 			ubi->ubi_name, ubi->ref_count);
 	}
 	ubi_devices[ubi_num] = NULL;
@@ -1132,11 +1137,14 @@
 
 	ubi_assert(ubi_num == ubi->ubi_num);
 	ubi_notify_all(ubi, UBI_VOLUME_REMOVED, NULL);
-	ubi_msg("detaching mtd%d from ubi%d", ubi->mtd->index, ubi_num);
+	ubi_msg(ubi, "detaching mtd%d", ubi->mtd->index);
 #ifdef CONFIG_MTD_UBI_FASTMAP
 	/* If we don't write a new fastmap at detach time we lose all
-	 * EC updates that have been made since the last written fastmap. */
-	ubi_update_fastmap(ubi);
+	 * EC updates that have been made since the last written fastmap.
+	 * In case of fastmap debugging we omit the update to simulate an
+	 * unclean shutdown. */
+	if (!ubi_dbg_chk_fastmap(ubi))
+		ubi_update_fastmap(ubi);
 #endif
 	/*
 	 * Before freeing anything, we have to stop the background thread to
@@ -1160,7 +1168,7 @@
 	put_mtd_device(ubi->mtd);
 	vfree(ubi->peb_buf);
 	vfree(ubi->fm_buf);
-	ubi_msg("mtd%d is detached from ubi%d", ubi->mtd->index, ubi->ubi_num);
+	ubi_msg(ubi, "mtd%d is detached", ubi->mtd->index);
 	put_device(&ubi->dev);
 	return 0;
 }
@@ -1185,9 +1193,9 @@
 		return ERR_PTR(err);
 
 	/* MTD device number is defined by the major / minor numbers */
-	major = imajor(path.dentry->d_inode);
-	minor = iminor(path.dentry->d_inode);
-	mode = path.dentry->d_inode->i_mode;
+	major = imajor(d_backing_inode(path.dentry));
+	minor = iminor(d_backing_inode(path.dentry));
+	mode = d_backing_inode(path.dentry)->i_mode;
 	path_put(&path);
 	if (major != MTD_CHAR_MAJOR || !S_ISCHR(mode))
 		return ERR_PTR(-EINVAL);
@@ -1250,28 +1258,20 @@
 	BUILD_BUG_ON(sizeof(struct ubi_vid_hdr) != 64);
 
 	if (mtd_devs > UBI_MAX_DEVICES) {
-		ubi_err("too many MTD devices, maximum is %d", UBI_MAX_DEVICES);
+		pr_err("UBI error: too many MTD devices, maximum is %d",
+		       UBI_MAX_DEVICES);
 		return -EINVAL;
 	}
 
 	/* Create base sysfs directory and sysfs files */
-	ubi_class = class_create(THIS_MODULE, UBI_NAME_STR);
-	if (IS_ERR(ubi_class)) {
-		err = PTR_ERR(ubi_class);
-		ubi_err("cannot create UBI class");
-		goto out;
-	}
-
-	err = class_create_file(ubi_class, &ubi_version);
-	if (err) {
-		ubi_err("cannot create sysfs file");
-		goto out_class;
-	}
+	err = class_register(&ubi_class);
+	if (err < 0)
+		return err;
 
 	err = misc_register(&ubi_ctrl_cdev);
 	if (err) {
-		ubi_err("cannot register device");
-		goto out_version;
+		pr_err("UBI error: cannot register device");
+		goto out;
 	}
 
 	ubi_wl_entry_slab = kmem_cache_create("ubi_wl_entry_slab",
@@ -1297,7 +1297,8 @@
 		mtd = open_mtd_device(p->name);
 		if (IS_ERR(mtd)) {
 			err = PTR_ERR(mtd);
-			ubi_err("cannot open mtd %s, error %d", p->name, err);
+			pr_err("UBI error: cannot open mtd %s, error %d",
+			       p->name, err);
 			/* See comment below re-ubi_is_module(). */
 			if (ubi_is_module())
 				goto out_detach;
@@ -1309,7 +1310,8 @@
 					 p->vid_hdr_offs, p->max_beb_per1024);
 		mutex_unlock(&ubi_devices_mutex);
 		if (err < 0) {
-			ubi_err("cannot attach mtd%d", mtd->index);
+			pr_err("UBI error: cannot attach mtd%d",
+			       mtd->index);
 			put_mtd_device(mtd);
 
 			/*
@@ -1332,7 +1334,7 @@
 
 	err = ubiblock_init();
 	if (err) {
-		ubi_err("block: cannot initialize, error %d", err);
+		pr_err("UBI error: block: cannot initialize, error %d", err);
 
 		/* See comment above re-ubi_is_module(). */
 		if (ubi_is_module())
@@ -1353,16 +1355,13 @@
 	kmem_cache_destroy(ubi_wl_entry_slab);
 out_dev_unreg:
 	misc_deregister(&ubi_ctrl_cdev);
-out_version:
-	class_remove_file(ubi_class, &ubi_version);
-out_class:
-	class_destroy(ubi_class);
 out:
 #ifdef __UBOOT__
 	/* Reset any globals that the driver depends on being zeroed */
 	mtd_devs = 0;
 #endif
-	ubi_err("cannot initialize UBI, error %d", err);
+	class_unregister(&ubi_class);
+	pr_err("UBI error: cannot initialize UBI, error %d", err);
 	return err;
 }
 late_initcall(ubi_init);
@@ -1386,8 +1385,7 @@
 	ubi_debugfs_exit();
 	kmem_cache_destroy(ubi_wl_entry_slab);
 	misc_deregister(&ubi_ctrl_cdev);
-	class_remove_file(ubi_class, &ubi_version);
-	class_destroy(ubi_class);
+	class_unregister(&ubi_class);
 #ifdef __UBOOT__
 	/* Reset any globals that the driver depends on being zeroed */
 	mtd_devs = 0;
@@ -1409,7 +1407,7 @@
 
 	result = simple_strtoul(str, &endp, 0);
 	if (str == endp || result >= INT_MAX) {
-		ubi_err("incorrect bytes count: \"%s\"\n", str);
+		pr_err("UBI error: incorrect bytes count: \"%s\"\n", str);
 		return -EINVAL;
 	}
 
@@ -1425,7 +1423,7 @@
 	case '\0':
 		break;
 	default:
-		ubi_err("incorrect bytes count: \"%s\"\n", str);
+		pr_err("UBI error: incorrect bytes count: \"%s\"\n", str);
 		return -EINVAL;
 	}
 
@@ -1467,15 +1465,15 @@
 		return -EINVAL;
 
 	if (mtd_devs == UBI_MAX_DEVICES) {
-		ubi_err("too many parameters, max. is %d\n",
-			UBI_MAX_DEVICES);
+		pr_err("UBI error: too many parameters, max. is %d\n",
+		       UBI_MAX_DEVICES);
 		return -EINVAL;
 	}
 
 	len = strnlen(val, MTD_PARAM_LEN_MAX);
 	if (len == MTD_PARAM_LEN_MAX) {
-		ubi_err("parameter \"%s\" is too long, max. is %d\n",
-			val, MTD_PARAM_LEN_MAX);
+		pr_err("UBI error: parameter \"%s\" is too long, max. is %d\n",
+		       val, MTD_PARAM_LEN_MAX);
 		return -EINVAL;
 	}
 
@@ -1494,7 +1492,7 @@
 		tokens[i] = strsep(&pbuf, ",");
 
 	if (pbuf) {
-		ubi_err("too many arguments at \"%s\"\n", val);
+		pr_err("UBI error: too many arguments at \"%s\"\n", val);
 		return -EINVAL;
 	}
 
@@ -1514,8 +1512,8 @@
 		int err = kstrtoint(token, 10, &p->max_beb_per1024);
 
 		if (err) {
-			ubi_err("bad value for max_beb_per1024 parameter: %s",
-				token);
+			pr_err("UBI error: bad value for max_beb_per1024 parameter: %s",
+			       token);
 			return -EINVAL;
 		}
 	}
@@ -1525,7 +1523,8 @@
 		int err = kstrtoint(token, 10, &p->ubi_num);
 
 		if (err) {
-			ubi_err("bad value for ubi_num parameter: %s", token);
+			pr_err("UBI error: bad value for ubi_num parameter: %s",
+			       token);
 			return -EINVAL;
 		}
 	} else
@@ -1552,6 +1551,8 @@
 #ifdef CONFIG_MTD_UBI_FASTMAP
 module_param(fm_autoconvert, bool, 0644);
 MODULE_PARM_DESC(fm_autoconvert, "Set this parameter to enable fastmap automatically on images without a fastmap.");
+module_param(fm_debug, bool, 0);
+MODULE_PARM_DESC(fm_debug, "Set this parameter to enable fastmap debugging by default. Warning, this will make fastmap slow!");
 #endif
 MODULE_VERSION(__stringify(UBI_VERSION));
 MODULE_DESCRIPTION("UBI - Unsorted Block Images");
diff --git a/drivers/mtd/ubi/debug.c b/drivers/mtd/ubi/debug.c
index 6dcc4e4..c35c85b 100644
--- a/drivers/mtd/ubi/debug.c
+++ b/drivers/mtd/ubi/debug.c
@@ -33,12 +33,12 @@
 		return;
 	err = mtd_read(ubi->mtd, addr, len, &read, buf);
 	if (err && err != -EUCLEAN) {
-		ubi_err("error %d while reading %d bytes from PEB %d:%d, read %zd bytes",
+		ubi_err(ubi, "err %d while reading %d bytes from PEB %d:%d, read %zd bytes",
 			err, len, pnum, offset, read);
 		goto out;
 	}
 
-	ubi_msg("dumping %d bytes of data from PEB %d, offset %d",
+	ubi_msg(ubi, "dumping %d bytes of data from PEB %d, offset %d",
 		len, pnum, offset);
 	print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, buf, len, 1);
 out:
@@ -229,8 +229,8 @@
 	if (IS_ERR_OR_NULL(dfs_rootdir)) {
 		int err = dfs_rootdir ? -ENODEV : PTR_ERR(dfs_rootdir);
 
-		ubi_err("cannot create \"ubi\" debugfs directory, error %d\n",
-			err);
+		pr_err("UBI error: cannot create \"ubi\" debugfs directory, error %d\n",
+		       err);
 		return err;
 	}
 
@@ -254,7 +254,7 @@
 	struct dentry *dent = file->f_path.dentry;
 	struct ubi_device *ubi;
 	struct ubi_debug_info *d;
-	char buf[3];
+	char buf[8];
 	int val;
 
 	ubi = ubi_get_device(ubi_num);
@@ -266,12 +266,30 @@
 		val = d->chk_gen;
 	else if (dent == d->dfs_chk_io)
 		val = d->chk_io;
+	else if (dent == d->dfs_chk_fastmap)
+		val = d->chk_fastmap;
 	else if (dent == d->dfs_disable_bgt)
 		val = d->disable_bgt;
 	else if (dent == d->dfs_emulate_bitflips)
 		val = d->emulate_bitflips;
 	else if (dent == d->dfs_emulate_io_failures)
 		val = d->emulate_io_failures;
+	else if (dent == d->dfs_emulate_power_cut) {
+		snprintf(buf, sizeof(buf), "%u\n", d->emulate_power_cut);
+		count = simple_read_from_buffer(user_buf, count, ppos,
+						buf, strlen(buf));
+		goto out;
+	} else if (dent == d->dfs_power_cut_min) {
+		snprintf(buf, sizeof(buf), "%u\n", d->power_cut_min);
+		count = simple_read_from_buffer(user_buf, count, ppos,
+						buf, strlen(buf));
+		goto out;
+	} else if (dent == d->dfs_power_cut_max) {
+		snprintf(buf, sizeof(buf), "%u\n", d->power_cut_max);
+		count = simple_read_from_buffer(user_buf, count, ppos,
+						buf, strlen(buf));
+		goto out;
+	}
 	else {
 		count = -EINVAL;
 		goto out;
@@ -300,7 +318,7 @@
 	struct ubi_device *ubi;
 	struct ubi_debug_info *d;
 	size_t buf_size;
-	char buf[8];
+	char buf[8] = {0};
 	int val;
 
 	ubi = ubi_get_device(ubi_num);
@@ -314,6 +332,21 @@
 		goto out;
 	}
 
+	if (dent == d->dfs_power_cut_min) {
+		if (kstrtouint(buf, 0, &d->power_cut_min) != 0)
+			count = -EINVAL;
+		goto out;
+	} else if (dent == d->dfs_power_cut_max) {
+		if (kstrtouint(buf, 0, &d->power_cut_max) != 0)
+			count = -EINVAL;
+		goto out;
+	} else if (dent == d->dfs_emulate_power_cut) {
+		if (kstrtoint(buf, 0, &val) != 0)
+			count = -EINVAL;
+		d->emulate_power_cut = val;
+		goto out;
+	}
+
 	if (buf[0] == '1')
 		val = 1;
 	else if (buf[0] == '0')
@@ -327,6 +360,8 @@
 		d->chk_gen = val;
 	else if (dent == d->dfs_chk_io)
 		d->chk_io = val;
+	else if (dent == d->dfs_chk_fastmap)
+		d->chk_fastmap = val;
 	else if (dent == d->dfs_disable_bgt)
 		d->disable_bgt = val;
 	else if (dent == d->dfs_emulate_bitflips)
@@ -397,6 +432,13 @@
 		goto out_remove;
 	d->dfs_chk_io = dent;
 
+	fname = "chk_fastmap";
+	dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num,
+				   &dfs_fops);
+	if (IS_ERR_OR_NULL(dent))
+		goto out_remove;
+	d->dfs_chk_fastmap = dent;
+
 	fname = "tst_disable_bgt";
 	dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num,
 				   &dfs_fops);
@@ -418,13 +460,34 @@
 		goto out_remove;
 	d->dfs_emulate_io_failures = dent;
 
+	fname = "tst_emulate_power_cut";
+	dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num,
+				   &dfs_fops);
+	if (IS_ERR_OR_NULL(dent))
+		goto out_remove;
+	d->dfs_emulate_power_cut = dent;
+
+	fname = "tst_emulate_power_cut_min";
+	dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num,
+				   &dfs_fops);
+	if (IS_ERR_OR_NULL(dent))
+		goto out_remove;
+	d->dfs_power_cut_min = dent;
+
+	fname = "tst_emulate_power_cut_max";
+	dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num,
+				   &dfs_fops);
+	if (IS_ERR_OR_NULL(dent))
+		goto out_remove;
+	d->dfs_power_cut_max = dent;
+
 	return 0;
 
 out_remove:
 	debugfs_remove_recursive(d->dfs_dir);
 out:
 	err = dent ? PTR_ERR(dent) : -ENODEV;
-	ubi_err("cannot create \"%s\" debugfs file or directory, error %d\n",
+	ubi_err(ubi, "cannot create \"%s\" debugfs file or directory, error %d\n",
 		fname, err);
 	return err;
 }
@@ -438,6 +501,39 @@
 	if (IS_ENABLED(CONFIG_DEBUG_FS))
 		debugfs_remove_recursive(ubi->dbg.dfs_dir);
 }
+
+/**
+ * ubi_dbg_power_cut - emulate a power cut if it is time to do so
+ * @ubi: UBI device description object
+ * @caller: Flags set to indicate from where the function is being called
+ *
+ * Returns non-zero if a power cut was emulated, zero if not.
+ */
+int ubi_dbg_power_cut(struct ubi_device *ubi, int caller)
+{
+	unsigned int range;
+
+	if ((ubi->dbg.emulate_power_cut & caller) == 0)
+		return 0;
+
+	if (ubi->dbg.power_cut_counter == 0) {
+		ubi->dbg.power_cut_counter = ubi->dbg.power_cut_min;
+
+		if (ubi->dbg.power_cut_max > ubi->dbg.power_cut_min) {
+			range = ubi->dbg.power_cut_max - ubi->dbg.power_cut_min;
+			ubi->dbg.power_cut_counter += prandom_u32() % range;
+		}
+		return 0;
+	}
+
+	ubi->dbg.power_cut_counter--;
+	if (ubi->dbg.power_cut_counter)
+		return 0;
+
+	ubi_msg(ubi, "XXXXXXXXXXXXXXX emulating a power cut XXXXXXXXXXXXXXXX");
+	ubi_ro_mode(ubi);
+	return 1;
+}
 #else
 int ubi_debugfs_init(void)
 {
@@ -455,5 +551,10 @@
 
 void ubi_debugfs_exit_dev(struct ubi_device *ubi)
 {
+}
+
+int ubi_dbg_power_cut(struct ubi_device *ubi, int caller)
+{
+	return 0;
 }
 #endif
diff --git a/drivers/mtd/ubi/debug.h b/drivers/mtd/ubi/debug.h
index bfa9dfb..d8d824e 100644
--- a/drivers/mtd/ubi/debug.h
+++ b/drivers/mtd/ubi/debug.h
@@ -117,4 +117,16 @@
 {
 	return ubi->dbg.chk_gen;
 }
+
+static inline int ubi_dbg_chk_fastmap(const struct ubi_device *ubi)
+{
+	return ubi->dbg.chk_fastmap;
+}
+
+static inline void ubi_enable_dbg_chk_fastmap(struct ubi_device *ubi)
+{
+	ubi->dbg.chk_fastmap = 1;
+}
+
+int ubi_dbg_power_cut(struct ubi_device *ubi, int caller);
 #endif /* !__UBI_DEBUG_H__ */
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c
index fce0ff8..6a78f67 100644
--- a/drivers/mtd/ubi/eba.c
+++ b/drivers/mtd/ubi/eba.c
@@ -333,9 +333,9 @@
 
 	dbg_eba("erase LEB %d:%d, PEB %d", vol_id, lnum, pnum);
 
-	down_read(&ubi->fm_sem);
+	down_read(&ubi->fm_eba_sem);
 	vol->eba_tbl[lnum] = UBI_LEB_UNMAPPED;
-	up_read(&ubi->fm_sem);
+	up_read(&ubi->fm_eba_sem);
 	err = ubi_wl_put_peb(ubi, vol_id, lnum, pnum, 0);
 
 out_unlock:
@@ -415,11 +415,13 @@
 				 */
 				if (err == UBI_IO_BAD_HDR_EBADMSG ||
 				    err == UBI_IO_BAD_HDR) {
-					ubi_warn("corrupted VID header at PEB %d, LEB %d:%d",
+					ubi_warn(ubi, "corrupted VID header at PEB %d, LEB %d:%d",
 						 pnum, vol_id, lnum);
 					err = -EBADMSG;
-				} else
+				} else {
+					err = -EINVAL;
 					ubi_ro_mode(ubi);
+				}
 			}
 			goto out_free;
 		} else if (err == UBI_IO_BITFLIPS)
@@ -434,15 +436,14 @@
 
 	err = ubi_io_read_data(ubi, buf, pnum, offset, len);
 	if (err) {
-		if (err == UBI_IO_BITFLIPS) {
+		if (err == UBI_IO_BITFLIPS)
 			scrub = 1;
-			err = 0;
-		} else if (mtd_is_eccerr(err)) {
+		else if (mtd_is_eccerr(err)) {
 			if (vol->vol_type == UBI_DYNAMIC_VOLUME)
 				goto out_unlock;
 			scrub = 1;
 			if (!check) {
-				ubi_msg("force data checking");
+				ubi_msg(ubi, "force data checking");
 				check = 1;
 				goto retry;
 			}
@@ -453,7 +454,7 @@
 	if (check) {
 		uint32_t crc1 = crc32(UBI_CRC32_INIT, buf, len);
 		if (crc1 != crc) {
-			ubi_warn("CRC error: calculated %#08x, must be %#08x",
+			ubi_warn(ubi, "CRC error: calculated %#08x, must be %#08x",
 				 crc1, crc);
 			err = -EBADMSG;
 			goto out_unlock;
@@ -473,6 +474,63 @@
 	return err;
 }
 
+#ifndef __UBOOT__
+/**
+ * ubi_eba_read_leb_sg - read data into a scatter gather list.
+ * @ubi: UBI device description object
+ * @vol: volume description object
+ * @lnum: logical eraseblock number
+ * @sgl: UBI scatter gather list to store the read data
+ * @offset: offset from where to read
+ * @len: how many bytes to read
+ * @check: data CRC check flag
+ *
+ * This function works exactly like ubi_eba_read_leb(). But instead of
+ * storing the read data into a buffer it writes to an UBI scatter gather
+ * list.
+ */
+int ubi_eba_read_leb_sg(struct ubi_device *ubi, struct ubi_volume *vol,
+			struct ubi_sgl *sgl, int lnum, int offset, int len,
+			int check)
+{
+	int to_read;
+	int ret;
+	struct scatterlist *sg;
+
+	for (;;) {
+		ubi_assert(sgl->list_pos < UBI_MAX_SG_COUNT);
+		sg = &sgl->sg[sgl->list_pos];
+		if (len < sg->length - sgl->page_pos)
+			to_read = len;
+		else
+			to_read = sg->length - sgl->page_pos;
+
+		ret = ubi_eba_read_leb(ubi, vol, lnum,
+				       sg_virt(sg) + sgl->page_pos, offset,
+				       to_read, check);
+		if (ret < 0)
+			return ret;
+
+		offset += to_read;
+		len -= to_read;
+		if (!len) {
+			sgl->page_pos += to_read;
+			if (sgl->page_pos == sg->length) {
+				sgl->list_pos++;
+				sgl->page_pos = 0;
+			}
+
+			break;
+		}
+
+		sgl->list_pos++;
+		sgl->page_pos = 0;
+	}
+
+	return ret;
+}
+#endif
+
 /**
  * recover_peb - recover from write failure.
  * @ubi: UBI device description object
@@ -504,22 +562,27 @@
 	new_pnum = ubi_wl_get_peb(ubi);
 	if (new_pnum < 0) {
 		ubi_free_vid_hdr(ubi, vid_hdr);
+		up_read(&ubi->fm_eba_sem);
 		return new_pnum;
 	}
 
-	ubi_msg("recover PEB %d, move data to PEB %d", pnum, new_pnum);
+	ubi_msg(ubi, "recover PEB %d, move data to PEB %d",
+		pnum, new_pnum);
 
 	err = ubi_io_read_vid_hdr(ubi, pnum, vid_hdr, 1);
 	if (err && err != UBI_IO_BITFLIPS) {
 		if (err > 0)
 			err = -EIO;
+		up_read(&ubi->fm_eba_sem);
 		goto out_put;
 	}
 
 	vid_hdr->sqnum = cpu_to_be64(ubi_next_sqnum(ubi));
 	err = ubi_io_write_vid_hdr(ubi, new_pnum, vid_hdr);
-	if (err)
+	if (err) {
+		up_read(&ubi->fm_eba_sem);
 		goto write_error;
+	}
 
 	data_size = offset + len;
 	mutex_lock(&ubi->buf_mutex);
@@ -528,8 +591,10 @@
 	/* Read everything before the area where the write failure happened */
 	if (offset > 0) {
 		err = ubi_io_read_data(ubi, ubi->peb_buf, pnum, 0, offset);
-		if (err && err != UBI_IO_BITFLIPS)
+		if (err && err != UBI_IO_BITFLIPS) {
+			up_read(&ubi->fm_eba_sem);
 			goto out_unlock;
+		}
 	}
 
 	memcpy(ubi->peb_buf + offset, buf, len);
@@ -537,18 +602,18 @@
 	err = ubi_io_write_data(ubi, ubi->peb_buf, new_pnum, 0, data_size);
 	if (err) {
 		mutex_unlock(&ubi->buf_mutex);
+		up_read(&ubi->fm_eba_sem);
 		goto write_error;
 	}
 
 	mutex_unlock(&ubi->buf_mutex);
 	ubi_free_vid_hdr(ubi, vid_hdr);
 
-	down_read(&ubi->fm_sem);
 	vol->eba_tbl[lnum] = new_pnum;
-	up_read(&ubi->fm_sem);
+	up_read(&ubi->fm_eba_sem);
 	ubi_wl_put_peb(ubi, vol_id, lnum, pnum, 1);
 
-	ubi_msg("data was successfully recovered");
+	ubi_msg(ubi, "data was successfully recovered");
 	return 0;
 
 out_unlock:
@@ -563,13 +628,13 @@
 	 * Bad luck? This physical eraseblock is bad too? Crud. Let's try to
 	 * get another one.
 	 */
-	ubi_warn("failed to write to PEB %d", new_pnum);
+	ubi_warn(ubi, "failed to write to PEB %d", new_pnum);
 	ubi_wl_put_peb(ubi, vol_id, lnum, new_pnum, 1);
 	if (++tries > UBI_IO_RETRIES) {
 		ubi_free_vid_hdr(ubi, vid_hdr);
 		return err;
 	}
-	ubi_msg("try again");
+	ubi_msg(ubi, "try again");
 	goto retry;
 }
 
@@ -607,7 +672,7 @@
 
 		err = ubi_io_write_data(ubi, buf, pnum, offset, len);
 		if (err) {
-			ubi_warn("failed to write data to PEB %d", pnum);
+			ubi_warn(ubi, "failed to write data to PEB %d", pnum);
 			if (err == -EIO && ubi->bad_allowed)
 				err = recover_peb(ubi, pnum, vol_id, lnum, buf,
 						  offset, len);
@@ -640,6 +705,7 @@
 	if (pnum < 0) {
 		ubi_free_vid_hdr(ubi, vid_hdr);
 		leb_write_unlock(ubi, vol_id, lnum);
+		up_read(&ubi->fm_eba_sem);
 		return pnum;
 	}
 
@@ -648,23 +714,24 @@
 
 	err = ubi_io_write_vid_hdr(ubi, pnum, vid_hdr);
 	if (err) {
-		ubi_warn("failed to write VID header to LEB %d:%d, PEB %d",
+		ubi_warn(ubi, "failed to write VID header to LEB %d:%d, PEB %d",
 			 vol_id, lnum, pnum);
+		up_read(&ubi->fm_eba_sem);
 		goto write_error;
 	}
 
 	if (len) {
 		err = ubi_io_write_data(ubi, buf, pnum, offset, len);
 		if (err) {
-			ubi_warn("failed to write %d bytes at offset %d of LEB %d:%d, PEB %d",
+			ubi_warn(ubi, "failed to write %d bytes at offset %d of LEB %d:%d, PEB %d",
 				 len, offset, vol_id, lnum, pnum);
+			up_read(&ubi->fm_eba_sem);
 			goto write_error;
 		}
 	}
 
-	down_read(&ubi->fm_sem);
 	vol->eba_tbl[lnum] = pnum;
-	up_read(&ubi->fm_sem);
+	up_read(&ubi->fm_eba_sem);
 
 	leb_write_unlock(ubi, vol_id, lnum);
 	ubi_free_vid_hdr(ubi, vid_hdr);
@@ -692,7 +759,7 @@
 	}
 
 	vid_hdr->sqnum = cpu_to_be64(ubi_next_sqnum(ubi));
-	ubi_msg("try another PEB");
+	ubi_msg(ubi, "try another PEB");
 	goto retry;
 }
 
@@ -761,6 +828,7 @@
 	if (pnum < 0) {
 		ubi_free_vid_hdr(ubi, vid_hdr);
 		leb_write_unlock(ubi, vol_id, lnum);
+		up_read(&ubi->fm_eba_sem);
 		return pnum;
 	}
 
@@ -769,22 +837,23 @@
 
 	err = ubi_io_write_vid_hdr(ubi, pnum, vid_hdr);
 	if (err) {
-		ubi_warn("failed to write VID header to LEB %d:%d, PEB %d",
+		ubi_warn(ubi, "failed to write VID header to LEB %d:%d, PEB %d",
 			 vol_id, lnum, pnum);
+		up_read(&ubi->fm_eba_sem);
 		goto write_error;
 	}
 
 	err = ubi_io_write_data(ubi, buf, pnum, 0, len);
 	if (err) {
-		ubi_warn("failed to write %d bytes of data to PEB %d",
+		ubi_warn(ubi, "failed to write %d bytes of data to PEB %d",
 			 len, pnum);
+		up_read(&ubi->fm_eba_sem);
 		goto write_error;
 	}
 
 	ubi_assert(vol->eba_tbl[lnum] < 0);
-	down_read(&ubi->fm_sem);
 	vol->eba_tbl[lnum] = pnum;
-	up_read(&ubi->fm_sem);
+	up_read(&ubi->fm_eba_sem);
 
 	leb_write_unlock(ubi, vol_id, lnum);
 	ubi_free_vid_hdr(ubi, vid_hdr);
@@ -812,7 +881,7 @@
 	}
 
 	vid_hdr->sqnum = cpu_to_be64(ubi_next_sqnum(ubi));
-	ubi_msg("try another PEB");
+	ubi_msg(ubi, "try another PEB");
 	goto retry;
 }
 
@@ -836,7 +905,7 @@
 int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,
 			      int lnum, const void *buf, int len)
 {
-	int err, pnum, tries = 0, vol_id = vol->vol_id;
+	int err, pnum, old_pnum, tries = 0, vol_id = vol->vol_id;
 	struct ubi_vid_hdr *vid_hdr;
 	uint32_t crc;
 
@@ -879,6 +948,7 @@
 	pnum = ubi_wl_get_peb(ubi);
 	if (pnum < 0) {
 		err = pnum;
+		up_read(&ubi->fm_eba_sem);
 		goto out_leb_unlock;
 	}
 
@@ -887,28 +957,30 @@
 
 	err = ubi_io_write_vid_hdr(ubi, pnum, vid_hdr);
 	if (err) {
-		ubi_warn("failed to write VID header to LEB %d:%d, PEB %d",
+		ubi_warn(ubi, "failed to write VID header to LEB %d:%d, PEB %d",
 			 vol_id, lnum, pnum);
+		up_read(&ubi->fm_eba_sem);
 		goto write_error;
 	}
 
 	err = ubi_io_write_data(ubi, buf, pnum, 0, len);
 	if (err) {
-		ubi_warn("failed to write %d bytes of data to PEB %d",
+		ubi_warn(ubi, "failed to write %d bytes of data to PEB %d",
 			 len, pnum);
+		up_read(&ubi->fm_eba_sem);
 		goto write_error;
 	}
 
-	if (vol->eba_tbl[lnum] >= 0) {
-		err = ubi_wl_put_peb(ubi, vol_id, lnum, vol->eba_tbl[lnum], 0);
+	old_pnum = vol->eba_tbl[lnum];
+	vol->eba_tbl[lnum] = pnum;
+	up_read(&ubi->fm_eba_sem);
+
+	if (old_pnum >= 0) {
+		err = ubi_wl_put_peb(ubi, vol_id, lnum, old_pnum, 0);
 		if (err)
 			goto out_leb_unlock;
 	}
 
-	down_read(&ubi->fm_sem);
-	vol->eba_tbl[lnum] = pnum;
-	up_read(&ubi->fm_sem);
-
 out_leb_unlock:
 	leb_write_unlock(ubi, vol_id, lnum);
 out_mutex:
@@ -934,7 +1006,7 @@
 	}
 
 	vid_hdr->sqnum = cpu_to_be64(ubi_next_sqnum(ubi));
-	ubi_msg("try another PEB");
+	ubi_msg(ubi, "try another PEB");
 	goto retry;
 }
 
@@ -1057,7 +1129,7 @@
 	dbg_wl("read %d bytes of data", aldata_size);
 	err = ubi_io_read_data(ubi, ubi->peb_buf, from, 0, aldata_size);
 	if (err && err != UBI_IO_BITFLIPS) {
-		ubi_warn("error %d while reading data from PEB %d",
+		ubi_warn(ubi, "error %d while reading data from PEB %d",
 			 err, from);
 		err = MOVE_SOURCE_RD_ERR;
 		goto out_unlock_buf;
@@ -1107,7 +1179,7 @@
 	err = ubi_io_read_vid_hdr(ubi, to, vid_hdr, 1);
 	if (err) {
 		if (err != UBI_IO_BITFLIPS) {
-			ubi_warn("error %d while reading VID header back from PEB %d",
+			ubi_warn(ubi, "error %d while reading VID header back from PEB %d",
 				 err, to);
 			if (is_error_sane(err))
 				err = MOVE_TARGET_RD_ERR;
@@ -1134,7 +1206,7 @@
 		err = ubi_io_read_data(ubi, ubi->peb_buf, to, 0, aldata_size);
 		if (err) {
 			if (err != UBI_IO_BITFLIPS) {
-				ubi_warn("error %d while reading data back from PEB %d",
+				ubi_warn(ubi, "error %d while reading data back from PEB %d",
 					 err, to);
 				if (is_error_sane(err))
 					err = MOVE_TARGET_RD_ERR;
@@ -1146,7 +1218,7 @@
 		cond_resched();
 
 		if (crc != crc32(UBI_CRC32_INIT, ubi->peb_buf, data_size)) {
-			ubi_warn("read data back from PEB %d and it is different",
+			ubi_warn(ubi, "read data back from PEB %d and it is different",
 				 to);
 			err = -EINVAL;
 			goto out_unlock_buf;
@@ -1154,9 +1226,9 @@
 	}
 
 	ubi_assert(vol->eba_tbl[lnum] == from);
-	down_read(&ubi->fm_sem);
+	down_read(&ubi->fm_eba_sem);
 	vol->eba_tbl[lnum] = to;
-	up_read(&ubi->fm_sem);
+	up_read(&ubi->fm_eba_sem);
 
 out_unlock_buf:
 	mutex_unlock(&ubi->buf_mutex);
@@ -1199,10 +1271,10 @@
 			return;
 	}
 
-	ubi_warn("cannot reserve enough PEBs for bad PEB handling, reserved %d, need %d",
+	ubi_warn(ubi, "cannot reserve enough PEBs for bad PEB handling, reserved %d, need %d",
 		 ubi->beb_rsvd_pebs, ubi->beb_rsvd_level);
 	if (ubi->corr_peb_count)
-		ubi_warn("%d PEBs are corrupted and not used",
+		ubi_warn(ubi, "%d PEBs are corrupted and not used",
 			 ubi->corr_peb_count);
 }
 
@@ -1280,7 +1352,7 @@
 					fm_eba[i][j] == UBI_LEB_UNMAPPED)
 					continue;
 
-				ubi_err("LEB:%i:%i is PEB:%i instead of %i!",
+				ubi_err(ubi, "LEB:%i:%i is PEB:%i instead of %i!",
 					vol->vol_id, i, fm_eba[i][j],
 					scan_eba[i][j]);
 				ubi_assert(0);
@@ -1355,15 +1427,16 @@
 				 * during re-size.
 				 */
 				ubi_move_aeb_to_list(av, aeb, &ai->erase);
-			vol->eba_tbl[aeb->lnum] = aeb->pnum;
+			else
+				vol->eba_tbl[aeb->lnum] = aeb->pnum;
 		}
 	}
 
 	if (ubi->avail_pebs < EBA_RESERVED_PEBS) {
-		ubi_err("no enough physical eraseblocks (%d, need %d)",
+		ubi_err(ubi, "no enough physical eraseblocks (%d, need %d)",
 			ubi->avail_pebs, EBA_RESERVED_PEBS);
 		if (ubi->corr_peb_count)
-			ubi_err("%d PEBs are corrupted and not used",
+			ubi_err(ubi, "%d PEBs are corrupted and not used",
 				ubi->corr_peb_count);
 		err = -ENOSPC;
 		goto out_free;
diff --git a/drivers/mtd/ubi/fastmap-wl.c b/drivers/mtd/ubi/fastmap-wl.c
new file mode 100644
index 0000000..a33d406
--- /dev/null
+++ b/drivers/mtd/ubi/fastmap-wl.c
@@ -0,0 +1,372 @@
+/*
+ * Copyright (c) 2012 Linutronix GmbH
+ * Copyright (c) 2014 sigma star gmbh
+ * Author: Richard Weinberger <richard@nod.at>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ *
+ */
+
+/**
+ * update_fastmap_work_fn - calls ubi_update_fastmap from a work queue
+ * @wrk: the work description object
+ */
+#ifndef __UBOOT__
+static void update_fastmap_work_fn(struct work_struct *wrk)
+#else
+void update_fastmap_work_fn(struct ubi_device *ubi)
+#endif
+{
+#ifndef __UBOOT__
+	struct ubi_device *ubi = container_of(wrk, struct ubi_device, fm_work);
+#endif
+
+	ubi_update_fastmap(ubi);
+	spin_lock(&ubi->wl_lock);
+	ubi->fm_work_scheduled = 0;
+	spin_unlock(&ubi->wl_lock);
+}
+
+/**
+ * find_anchor_wl_entry - find wear-leveling entry to used as anchor PEB.
+ * @root: the RB-tree where to look for
+ */
+static struct ubi_wl_entry *find_anchor_wl_entry(struct rb_root *root)
+{
+	struct rb_node *p;
+	struct ubi_wl_entry *e, *victim = NULL;
+	int max_ec = UBI_MAX_ERASECOUNTER;
+
+	ubi_rb_for_each_entry(p, e, root, u.rb) {
+		if (e->pnum < UBI_FM_MAX_START && e->ec < max_ec) {
+			victim = e;
+			max_ec = e->ec;
+		}
+	}
+
+	return victim;
+}
+
+/**
+ * return_unused_pool_pebs - returns unused PEB to the free tree.
+ * @ubi: UBI device description object
+ * @pool: fastmap pool description object
+ */
+static void return_unused_pool_pebs(struct ubi_device *ubi,
+				    struct ubi_fm_pool *pool)
+{
+	int i;
+	struct ubi_wl_entry *e;
+
+	for (i = pool->used; i < pool->size; i++) {
+		e = ubi->lookuptbl[pool->pebs[i]];
+		wl_tree_add(e, &ubi->free);
+		ubi->free_count++;
+	}
+}
+
+static int anchor_pebs_avalible(struct rb_root *root)
+{
+	struct rb_node *p;
+	struct ubi_wl_entry *e;
+
+	ubi_rb_for_each_entry(p, e, root, u.rb)
+		if (e->pnum < UBI_FM_MAX_START)
+			return 1;
+
+	return 0;
+}
+
+/**
+ * ubi_wl_get_fm_peb - find a physical erase block with a given maximal number.
+ * @ubi: UBI device description object
+ * @anchor: This PEB will be used as anchor PEB by fastmap
+ *
+ * The function returns a physical erase block with a given maximal number
+ * and removes it from the wl subsystem.
+ * Must be called with wl_lock held!
+ */
+struct ubi_wl_entry *ubi_wl_get_fm_peb(struct ubi_device *ubi, int anchor)
+{
+	struct ubi_wl_entry *e = NULL;
+
+	if (!ubi->free.rb_node || (ubi->free_count - ubi->beb_rsvd_pebs < 1))
+		goto out;
+
+	if (anchor)
+		e = find_anchor_wl_entry(&ubi->free);
+	else
+		e = find_mean_wl_entry(ubi, &ubi->free);
+
+	if (!e)
+		goto out;
+
+	self_check_in_wl_tree(ubi, e, &ubi->free);
+
+	/* remove it from the free list,
+	 * the wl subsystem does no longer know this erase block */
+	rb_erase(&e->u.rb, &ubi->free);
+	ubi->free_count--;
+out:
+	return e;
+}
+
+/**
+ * ubi_refill_pools - refills all fastmap PEB pools.
+ * @ubi: UBI device description object
+ */
+void ubi_refill_pools(struct ubi_device *ubi)
+{
+	struct ubi_fm_pool *wl_pool = &ubi->fm_wl_pool;
+	struct ubi_fm_pool *pool = &ubi->fm_pool;
+	struct ubi_wl_entry *e;
+	int enough;
+
+	spin_lock(&ubi->wl_lock);
+
+	return_unused_pool_pebs(ubi, wl_pool);
+	return_unused_pool_pebs(ubi, pool);
+
+	wl_pool->size = 0;
+	pool->size = 0;
+
+	for (;;) {
+		enough = 0;
+		if (pool->size < pool->max_size) {
+			if (!ubi->free.rb_node)
+				break;
+
+			e = wl_get_wle(ubi);
+			if (!e)
+				break;
+
+			pool->pebs[pool->size] = e->pnum;
+			pool->size++;
+		} else
+			enough++;
+
+		if (wl_pool->size < wl_pool->max_size) {
+			if (!ubi->free.rb_node ||
+			   (ubi->free_count - ubi->beb_rsvd_pebs < 5))
+				break;
+
+			e = find_wl_entry(ubi, &ubi->free, WL_FREE_MAX_DIFF);
+			self_check_in_wl_tree(ubi, e, &ubi->free);
+			rb_erase(&e->u.rb, &ubi->free);
+			ubi->free_count--;
+
+			wl_pool->pebs[wl_pool->size] = e->pnum;
+			wl_pool->size++;
+		} else
+			enough++;
+
+		if (enough == 2)
+			break;
+	}
+
+	wl_pool->used = 0;
+	pool->used = 0;
+
+	spin_unlock(&ubi->wl_lock);
+}
+
+/**
+ * ubi_wl_get_peb - get a physical eraseblock.
+ * @ubi: UBI device description object
+ *
+ * This function returns a physical eraseblock in case of success and a
+ * negative error code in case of failure.
+ * Returns with ubi->fm_eba_sem held in read mode!
+ */
+int ubi_wl_get_peb(struct ubi_device *ubi)
+{
+	int ret, retried = 0;
+	struct ubi_fm_pool *pool = &ubi->fm_pool;
+	struct ubi_fm_pool *wl_pool = &ubi->fm_wl_pool;
+
+again:
+	down_read(&ubi->fm_eba_sem);
+	spin_lock(&ubi->wl_lock);
+
+	/* We check here also for the WL pool because at this point we can
+	 * refill the WL pool synchronous. */
+	if (pool->used == pool->size || wl_pool->used == wl_pool->size) {
+		spin_unlock(&ubi->wl_lock);
+		up_read(&ubi->fm_eba_sem);
+		ret = ubi_update_fastmap(ubi);
+		if (ret) {
+			ubi_msg(ubi, "Unable to write a new fastmap: %i", ret);
+			down_read(&ubi->fm_eba_sem);
+			return -ENOSPC;
+		}
+		down_read(&ubi->fm_eba_sem);
+		spin_lock(&ubi->wl_lock);
+	}
+
+	if (pool->used == pool->size) {
+		spin_unlock(&ubi->wl_lock);
+		if (retried) {
+			ubi_err(ubi, "Unable to get a free PEB from user WL pool");
+			ret = -ENOSPC;
+			goto out;
+		}
+		retried = 1;
+		up_read(&ubi->fm_eba_sem);
+		goto again;
+	}
+
+	ubi_assert(pool->used < pool->size);
+	ret = pool->pebs[pool->used++];
+	prot_queue_add(ubi, ubi->lookuptbl[ret]);
+	spin_unlock(&ubi->wl_lock);
+out:
+	return ret;
+}
+
+/* get_peb_for_wl - returns a PEB to be used internally by the WL sub-system.
+ *
+ * @ubi: UBI device description object
+ */
+static struct ubi_wl_entry *get_peb_for_wl(struct ubi_device *ubi)
+{
+	struct ubi_fm_pool *pool = &ubi->fm_wl_pool;
+	int pnum;
+
+	if (pool->used == pool->size) {
+#ifndef __UBOOT__
+		/* We cannot update the fastmap here because this
+		 * function is called in atomic context.
+		 * Let's fail here and refill/update it as soon as possible. */
+		if (!ubi->fm_work_scheduled) {
+			ubi->fm_work_scheduled = 1;
+			schedule_work(&ubi->fm_work);
+		}
+		return NULL;
+#else
+		/*
+		 * No work queues in U-Boot, we must do this immediately
+		 */
+		update_fastmap_work_fn(ubi);
+#endif
+	}
+
+	pnum = pool->pebs[pool->used++];
+	return ubi->lookuptbl[pnum];
+}
+
+/**
+ * ubi_ensure_anchor_pebs - schedule wear-leveling to produce an anchor PEB.
+ * @ubi: UBI device description object
+ */
+int ubi_ensure_anchor_pebs(struct ubi_device *ubi)
+{
+	struct ubi_work *wrk;
+
+	spin_lock(&ubi->wl_lock);
+	if (ubi->wl_scheduled) {
+		spin_unlock(&ubi->wl_lock);
+		return 0;
+	}
+	ubi->wl_scheduled = 1;
+	spin_unlock(&ubi->wl_lock);
+
+	wrk = kmalloc(sizeof(struct ubi_work), GFP_NOFS);
+	if (!wrk) {
+		spin_lock(&ubi->wl_lock);
+		ubi->wl_scheduled = 0;
+		spin_unlock(&ubi->wl_lock);
+		return -ENOMEM;
+	}
+
+	wrk->anchor = 1;
+	wrk->func = &wear_leveling_worker;
+	schedule_ubi_work(ubi, wrk);
+	return 0;
+}
+
+/**
+ * ubi_wl_put_fm_peb - returns a PEB used in a fastmap to the wear-leveling
+ * sub-system.
+ * see: ubi_wl_put_peb()
+ *
+ * @ubi: UBI device description object
+ * @fm_e: physical eraseblock to return
+ * @lnum: the last used logical eraseblock number for the PEB
+ * @torture: if this physical eraseblock has to be tortured
+ */
+int ubi_wl_put_fm_peb(struct ubi_device *ubi, struct ubi_wl_entry *fm_e,
+		      int lnum, int torture)
+{
+	struct ubi_wl_entry *e;
+	int vol_id, pnum = fm_e->pnum;
+
+	dbg_wl("PEB %d", pnum);
+
+	ubi_assert(pnum >= 0);
+	ubi_assert(pnum < ubi->peb_count);
+
+	spin_lock(&ubi->wl_lock);
+	e = ubi->lookuptbl[pnum];
+
+	/* This can happen if we recovered from a fastmap the very
+	 * first time and writing now a new one. In this case the wl system
+	 * has never seen any PEB used by the original fastmap.
+	 */
+	if (!e) {
+		e = fm_e;
+		ubi_assert(e->ec >= 0);
+		ubi->lookuptbl[pnum] = e;
+	}
+
+	spin_unlock(&ubi->wl_lock);
+
+	vol_id = lnum ? UBI_FM_DATA_VOLUME_ID : UBI_FM_SB_VOLUME_ID;
+	return schedule_erase(ubi, e, vol_id, lnum, torture);
+}
+
+/**
+ * ubi_is_erase_work - checks whether a work is erase work.
+ * @wrk: The work object to be checked
+ */
+int ubi_is_erase_work(struct ubi_work *wrk)
+{
+	return wrk->func == erase_worker;
+}
+
+static void ubi_fastmap_close(struct ubi_device *ubi)
+{
+	int i;
+
+#ifndef __UBOOT__
+	flush_work(&ubi->fm_work);
+#else
+	update_fastmap_work_fn(ubi);
+#endif
+	return_unused_pool_pebs(ubi, &ubi->fm_pool);
+	return_unused_pool_pebs(ubi, &ubi->fm_wl_pool);
+
+	if (ubi->fm) {
+		for (i = 0; i < ubi->fm->used_blocks; i++)
+			kfree(ubi->fm->e[i]);
+	}
+	kfree(ubi->fm);
+}
+
+/**
+ * may_reserve_for_fm - tests whether a PEB shall be reserved for fastmap.
+ * See find_mean_wl_entry()
+ *
+ * @ubi: UBI device description object
+ * @e: physical eraseblock to return
+ * @root: RB tree to test against.
+ */
+static struct ubi_wl_entry *may_reserve_for_fm(struct ubi_device *ubi,
+					   struct ubi_wl_entry *e,
+					   struct rb_root *root) {
+	if (e && !ubi->fm_disabled && !ubi->fm &&
+	    e->pnum < UBI_FM_MAX_START)
+		e = rb_entry(rb_next(root->rb_node),
+			     struct ubi_wl_entry, u.rb);
+
+	return e;
+}
diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c
index a2166e4..f824ec8 100644
--- a/drivers/mtd/ubi/fastmap.c
+++ b/drivers/mtd/ubi/fastmap.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2012 Linutronix GmbH
+ * Copyright (c) 2014 sigma star gmbh
  * Author: Richard Weinberger <richard@nod.at>
  *
  * SPDX-License-Identifier:	GPL-2.0+
@@ -19,6 +20,69 @@
 #include "ubi.h"
 
 /**
+ * init_seen - allocate memory for used for debugging.
+ * @ubi: UBI device description object
+ */
+static inline int *init_seen(struct ubi_device *ubi)
+{
+	int *ret;
+
+	if (!ubi_dbg_chk_fastmap(ubi))
+		return NULL;
+
+	ret = kcalloc(ubi->peb_count, sizeof(int), GFP_KERNEL);
+	if (!ret)
+		return ERR_PTR(-ENOMEM);
+
+	return ret;
+}
+
+/**
+ * free_seen - free the seen logic integer array.
+ * @seen: integer array of @ubi->peb_count size
+ */
+static inline void free_seen(int *seen)
+{
+	kfree(seen);
+}
+
+/**
+ * set_seen - mark a PEB as seen.
+ * @ubi: UBI device description object
+ * @pnum: The PEB to be makred as seen
+ * @seen: integer array of @ubi->peb_count size
+ */
+static inline void set_seen(struct ubi_device *ubi, int pnum, int *seen)
+{
+	if (!ubi_dbg_chk_fastmap(ubi) || !seen)
+		return;
+
+	seen[pnum] = 1;
+}
+
+/**
+ * self_check_seen - check whether all PEB have been seen by fastmap.
+ * @ubi: UBI device description object
+ * @seen: integer array of @ubi->peb_count size
+ */
+static int self_check_seen(struct ubi_device *ubi, int *seen)
+{
+	int pnum, ret = 0;
+
+	if (!ubi_dbg_chk_fastmap(ubi) || !seen)
+		return 0;
+
+	for (pnum = 0; pnum < ubi->peb_count; pnum++) {
+		if (!seen[pnum] && ubi->lookuptbl[pnum]) {
+			ubi_err(ubi, "self-check failed for PEB %d, fastmap didn't see it", pnum);
+			ret = -EINVAL;
+		}
+	}
+
+	return ret;
+}
+
+/**
  * ubi_calc_fm_size - calculates the fastmap size in bytes for an UBI device.
  * @ubi: UBI device description object
  */
@@ -26,12 +90,13 @@
 {
 	size_t size;
 
-	size = sizeof(struct ubi_fm_hdr) + \
-		sizeof(struct ubi_fm_scan_pool) + \
-		sizeof(struct ubi_fm_scan_pool) + \
-		(ubi->peb_count * sizeof(struct ubi_fm_ec)) + \
-		(sizeof(struct ubi_fm_eba) + \
-		(ubi->peb_count * sizeof(__be32))) + \
+	size = sizeof(struct ubi_fm_sb) +
+		sizeof(struct ubi_fm_hdr) +
+		sizeof(struct ubi_fm_scan_pool) +
+		sizeof(struct ubi_fm_scan_pool) +
+		(ubi->peb_count * sizeof(struct ubi_fm_ec)) +
+		(sizeof(struct ubi_fm_eba) +
+		(ubi->peb_count * sizeof(__be32))) +
 		sizeof(struct ubi_fm_volhdr) * UBI_MAX_VOLUMES;
 	return roundup(size, ubi->leb_size);
 }
@@ -129,22 +194,25 @@
 
 		if (vol_id > av->vol_id)
 			p = &(*p)->rb_left;
-		else if (vol_id > av->vol_id)
+		else if (vol_id < av->vol_id)
 			p = &(*p)->rb_right;
+		else
+			return ERR_PTR(-EINVAL);
 	}
 
 	av = kmalloc(sizeof(struct ubi_ainf_volume), GFP_KERNEL);
 	if (!av)
 		goto out;
 
-	av->highest_lnum = av->leb_count = 0;
+	av->highest_lnum = av->leb_count = av->used_ebs = 0;
 	av->vol_id = vol_id;
-	av->used_ebs = used_ebs;
 	av->data_pad = data_pad;
 	av->last_data_size = last_eb_bytes;
 	av->compat = 0;
 	av->vol_type = vol_type;
 	av->root = RB_ROOT;
+	if (av->vol_type == UBI_STATIC_VOLUME)
+		av->used_ebs = used_ebs;
 
 	dbg_bld("found volume (ID %i)", vol_id);
 
@@ -250,7 +318,7 @@
 			list_add_tail(&victim->u.list, &ai->erase);
 
 			if (av->highest_lnum == be32_to_cpu(new_vh->lnum))
-				av->last_data_size = \
+				av->last_data_size =
 					be32_to_cpu(new_vh->data_size);
 
 			dbg_bld("vol %i: AEB %i's PEB %i is the newer",
@@ -331,7 +399,8 @@
 	if (found)
 		av = tmp_av;
 	else {
-		ubi_err("orphaned volume in fastmap pool!");
+		ubi_err(ubi, "orphaned volume in fastmap pool!");
+		kmem_cache_free(ai->aeb_slab_cache, new_aeb);
 		return UBI_BAD_FASTMAP;
 	}
 
@@ -362,6 +431,7 @@
 			aeb = rb_entry(node2, struct ubi_ainf_peb, u.rb);
 			if (aeb->pnum == pnum) {
 				rb_erase(&aeb->u.rb, &av->root);
+				av->leb_count--;
 				kmem_cache_free(ai->aeb_slab_cache, aeb);
 				return;
 			}
@@ -376,7 +446,6 @@
  * @pebs: an array of all PEB numbers in the to be scanned pool
  * @pool_size: size of the pool (number of entries in @pebs)
  * @max_sqnum: pointer to the maximal sequence number
- * @eba_orphans: list of PEBs which need to be scanned
  * @free: list of PEBs which are most likely free (and go into @ai->free)
  *
  * Returns 0 on success, if the pool is unusable UBI_BAD_FASTMAP is returned.
@@ -384,18 +453,18 @@
  */
 #ifndef __UBOOT__
 static int scan_pool(struct ubi_device *ubi, struct ubi_attach_info *ai,
-		     int *pebs, int pool_size, unsigned long long *max_sqnum,
-		     struct list_head *eba_orphans, struct list_head *freef)
+		     __be32 *pebs, int pool_size, unsigned long long *max_sqnum,
+		     struct list_head *free)
 #else
 static int scan_pool(struct ubi_device *ubi, struct ubi_attach_info *ai,
 		     __be32 *pebs, int pool_size, unsigned long long *max_sqnum,
-		     struct list_head *eba_orphans, struct list_head *freef)
+		     struct list_head *free)
 #endif
 {
 	struct ubi_vid_hdr *vh;
 	struct ubi_ec_hdr *ech;
-	struct ubi_ainf_peb *new_aeb, *tmp_aeb;
-	int i, pnum, err, found_orphan, ret = 0;
+	struct ubi_ainf_peb *new_aeb;
+	int i, pnum, err, ret = 0;
 
 	ech = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL);
 	if (!ech)
@@ -420,18 +489,18 @@
 		pnum = be32_to_cpu(pebs[i]);
 
 		if (ubi_io_is_bad(ubi, pnum)) {
-			ubi_err("bad PEB in fastmap pool!");
+			ubi_err(ubi, "bad PEB in fastmap pool!");
 			ret = UBI_BAD_FASTMAP;
 			goto out;
 		}
 
 		err = ubi_io_read_ec_hdr(ubi, pnum, ech, 0);
 		if (err && err != UBI_IO_BITFLIPS) {
-			ubi_err("unable to read EC header! PEB:%i err:%i",
+			ubi_err(ubi, "unable to read EC header! PEB:%i err:%i",
 				pnum, err);
 			ret = err > 0 ? UBI_BAD_FASTMAP : err;
 			goto out;
-		} else if (ret == UBI_IO_BITFLIPS)
+		} else if (err == UBI_IO_BITFLIPS)
 			scrub = 1;
 
 		/*
@@ -441,7 +510,7 @@
 		image_seq = be32_to_cpu(ech->image_seq);
 
 		if (image_seq && (image_seq != ubi->image_seq)) {
-			ubi_err("bad image seq: 0x%x, expected: 0x%x",
+			ubi_err(ubi, "bad image seq: 0x%x, expected: 0x%x",
 				be32_to_cpu(ech->image_seq), ubi->image_seq);
 			ret = UBI_BAD_FASTMAP;
 			goto out;
@@ -453,9 +522,9 @@
 			unmap_peb(ai, pnum);
 			dbg_bld("Adding PEB to free: %i", pnum);
 			if (err == UBI_IO_FF_BITFLIPS)
-				add_aeb(ai, freef, pnum, ec, 1);
+				add_aeb(ai, free, pnum, ec, 1);
 			else
-				add_aeb(ai, freef, pnum, ec, 0);
+				add_aeb(ai, free, pnum, ec, 0);
 			continue;
 		} else if (err == 0 || err == UBI_IO_BITFLIPS) {
 			dbg_bld("Found non empty PEB:%i in pool", pnum);
@@ -463,18 +532,6 @@
 			if (err == UBI_IO_BITFLIPS)
 				scrub = 1;
 
-			found_orphan = 0;
-			list_for_each_entry(tmp_aeb, eba_orphans, u.list) {
-				if (tmp_aeb->pnum == pnum) {
-					found_orphan = 1;
-					break;
-				}
-			}
-			if (found_orphan) {
-				list_del(&tmp_aeb->u.list);
-				kmem_cache_free(ai->aeb_slab_cache, tmp_aeb);
-			}
-
 			new_aeb = kmem_cache_alloc(ai->aeb_slab_cache,
 						   GFP_KERNEL);
 			if (!new_aeb) {
@@ -499,7 +556,7 @@
 			}
 		} else {
 			/* We are paranoid and fall back to scanning mode */
-			ubi_err("fastmap pool PEBs contains damaged PEBs!");
+			ubi_err(ubi, "fastmap pool PEBs contains damaged PEBs!");
 			ret = err > 0 ? UBI_BAD_FASTMAP : err;
 			goto out;
 		}
@@ -549,13 +606,12 @@
 			      struct ubi_attach_info *ai,
 			      struct ubi_fastmap_layout *fm)
 {
-	struct list_head used, eba_orphans, freef;
+	struct list_head used, free;
 	struct ubi_ainf_volume *av;
 	struct ubi_ainf_peb *aeb, *tmp_aeb, *_tmp_aeb;
-	struct ubi_ec_hdr *ech;
 	struct ubi_fm_sb *fmsb;
 	struct ubi_fm_hdr *fmhdr;
-	struct ubi_fm_scan_pool *fmpl1, *fmpl2;
+	struct ubi_fm_scan_pool *fmpl, *fmpl_wl;
 	struct ubi_fm_ec *fmec;
 	struct ubi_fm_volhdr *fmvhdr;
 	struct ubi_fm_eba *fm_eba;
@@ -565,23 +621,9 @@
 	void *fm_raw = ubi->fm_buf;
 
 	INIT_LIST_HEAD(&used);
-	INIT_LIST_HEAD(&freef);
-	INIT_LIST_HEAD(&eba_orphans);
-	INIT_LIST_HEAD(&ai->corr);
-	INIT_LIST_HEAD(&ai->free);
-	INIT_LIST_HEAD(&ai->erase);
-	INIT_LIST_HEAD(&ai->alien);
-	ai->volumes = RB_ROOT;
+	INIT_LIST_HEAD(&free);
 	ai->min_ec = UBI_MAX_ERASECOUNTER;
 
-	ai->aeb_slab_cache = kmem_cache_create("ubi_ainf_peb_slab",
-					       sizeof(struct ubi_ainf_peb),
-					       0, 0, NULL);
-	if (!ai->aeb_slab_cache) {
-		ret = -ENOMEM;
-		goto fail;
-	}
-
 	fmsb = (struct ubi_fm_sb *)(fm_raw);
 	ai->max_sqnum = fmsb->sqnum;
 	fm_pos += sizeof(struct ubi_fm_sb);
@@ -594,56 +636,57 @@
 		goto fail_bad;
 
 	if (be32_to_cpu(fmhdr->magic) != UBI_FM_HDR_MAGIC) {
-		ubi_err("bad fastmap header magic: 0x%x, expected: 0x%x",
+		ubi_err(ubi, "bad fastmap header magic: 0x%x, expected: 0x%x",
 			be32_to_cpu(fmhdr->magic), UBI_FM_HDR_MAGIC);
 		goto fail_bad;
 	}
 
-	fmpl1 = (struct ubi_fm_scan_pool *)(fm_raw + fm_pos);
-	fm_pos += sizeof(*fmpl1);
+	fmpl = (struct ubi_fm_scan_pool *)(fm_raw + fm_pos);
+	fm_pos += sizeof(*fmpl);
 	if (fm_pos >= fm_size)
 		goto fail_bad;
-	if (be32_to_cpu(fmpl1->magic) != UBI_FM_POOL_MAGIC) {
-		ubi_err("bad fastmap pool magic: 0x%x, expected: 0x%x",
-			be32_to_cpu(fmpl1->magic), UBI_FM_POOL_MAGIC);
+	if (be32_to_cpu(fmpl->magic) != UBI_FM_POOL_MAGIC) {
+		ubi_err(ubi, "bad fastmap pool magic: 0x%x, expected: 0x%x",
+			be32_to_cpu(fmpl->magic), UBI_FM_POOL_MAGIC);
 		goto fail_bad;
 	}
 
-	fmpl2 = (struct ubi_fm_scan_pool *)(fm_raw + fm_pos);
-	fm_pos += sizeof(*fmpl2);
+	fmpl_wl = (struct ubi_fm_scan_pool *)(fm_raw + fm_pos);
+	fm_pos += sizeof(*fmpl_wl);
 	if (fm_pos >= fm_size)
 		goto fail_bad;
-	if (be32_to_cpu(fmpl2->magic) != UBI_FM_POOL_MAGIC) {
-		ubi_err("bad fastmap pool magic: 0x%x, expected: 0x%x",
-			be32_to_cpu(fmpl2->magic), UBI_FM_POOL_MAGIC);
+	if (be32_to_cpu(fmpl_wl->magic) != UBI_FM_POOL_MAGIC) {
+		ubi_err(ubi, "bad fastmap WL pool magic: 0x%x, expected: 0x%x",
+			be32_to_cpu(fmpl_wl->magic), UBI_FM_POOL_MAGIC);
 		goto fail_bad;
 	}
 
-	pool_size = be16_to_cpu(fmpl1->size);
-	wl_pool_size = be16_to_cpu(fmpl2->size);
-	fm->max_pool_size = be16_to_cpu(fmpl1->max_size);
-	fm->max_wl_pool_size = be16_to_cpu(fmpl2->max_size);
+	pool_size = be16_to_cpu(fmpl->size);
+	wl_pool_size = be16_to_cpu(fmpl_wl->size);
+	fm->max_pool_size = be16_to_cpu(fmpl->max_size);
+	fm->max_wl_pool_size = be16_to_cpu(fmpl_wl->max_size);
 
 	if (pool_size > UBI_FM_MAX_POOL_SIZE || pool_size < 0) {
-		ubi_err("bad pool size: %i", pool_size);
+		ubi_err(ubi, "bad pool size: %i", pool_size);
 		goto fail_bad;
 	}
 
 	if (wl_pool_size > UBI_FM_MAX_POOL_SIZE || wl_pool_size < 0) {
-		ubi_err("bad WL pool size: %i", wl_pool_size);
+		ubi_err(ubi, "bad WL pool size: %i", wl_pool_size);
 		goto fail_bad;
 	}
 
 
 	if (fm->max_pool_size > UBI_FM_MAX_POOL_SIZE ||
 	    fm->max_pool_size < 0) {
-		ubi_err("bad maximal pool size: %i", fm->max_pool_size);
+		ubi_err(ubi, "bad maximal pool size: %i", fm->max_pool_size);
 		goto fail_bad;
 	}
 
 	if (fm->max_wl_pool_size > UBI_FM_MAX_POOL_SIZE ||
 	    fm->max_wl_pool_size < 0) {
-		ubi_err("bad maximal WL pool size: %i", fm->max_wl_pool_size);
+		ubi_err(ubi, "bad maximal WL pool size: %i",
+			fm->max_wl_pool_size);
 		goto fail_bad;
 	}
 
@@ -702,8 +745,7 @@
 			goto fail_bad;
 
 		if (be32_to_cpu(fmvhdr->magic) != UBI_FM_VHDR_MAGIC) {
-			ubi_err("bad fastmap vol header magic: 0x%x, " \
-				"expected: 0x%x",
+			ubi_err(ubi, "bad fastmap vol header magic: 0x%x, expected: 0x%x",
 				be32_to_cpu(fmvhdr->magic), UBI_FM_VHDR_MAGIC);
 			goto fail_bad;
 		}
@@ -716,6 +758,11 @@
 
 		if (!av)
 			goto fail_bad;
+		if (PTR_ERR(av) == -EINVAL) {
+			ubi_err(ubi, "volume (ID %i) already exists",
+				fmvhdr->vol_id);
+			goto fail_bad;
+		}
 
 		ai->vols_found++;
 		if (ai->highest_vol_id < be32_to_cpu(fmvhdr->vol_id))
@@ -728,8 +775,7 @@
 			goto fail_bad;
 
 		if (be32_to_cpu(fm_eba->magic) != UBI_FM_EBA_MAGIC) {
-			ubi_err("bad fastmap EBA header magic: 0x%x, " \
-				"expected: 0x%x",
+			ubi_err(ubi, "bad fastmap EBA header magic: 0x%x, expected: 0x%x",
 				be32_to_cpu(fm_eba->magic), UBI_FM_EBA_MAGIC);
 			goto fail_bad;
 		}
@@ -748,28 +794,9 @@
 				}
 			}
 
-			/* This can happen if a PEB is already in an EBA known
-			 * by this fastmap but the PEB itself is not in the used
-			 * list.
-			 * In this case the PEB can be within the fastmap pool
-			 * or while writing the fastmap it was in the protection
-			 * queue.
-			 */
 			if (!aeb) {
-				aeb = kmem_cache_alloc(ai->aeb_slab_cache,
-						       GFP_KERNEL);
-				if (!aeb) {
-					ret = -ENOMEM;
-
-					goto fail;
-				}
-
-				aeb->lnum = j;
-				aeb->pnum = be32_to_cpu(fm_eba->pnum[j]);
-				aeb->ec = -1;
-				aeb->scrub = aeb->copy_flag = aeb->sqnum = 0;
-				list_add_tail(&aeb->u.list, &eba_orphans);
-				continue;
+				ubi_err(ubi, "PEB %i is in EBA but not in used list", pnum);
+				goto fail_bad;
 			}
 
 			aeb->lnum = j;
@@ -782,61 +809,26 @@
 			dbg_bld("inserting PEB:%i (LEB %i) to vol %i",
 				aeb->pnum, aeb->lnum, av->vol_id);
 		}
-
-		ech = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL);
-		if (!ech) {
-			ret = -ENOMEM;
-			goto fail;
-		}
-
-		list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &eba_orphans,
-					 u.list) {
-			int err;
-
-			if (ubi_io_is_bad(ubi, tmp_aeb->pnum)) {
-				ubi_err("bad PEB in fastmap EBA orphan list");
-				ret = UBI_BAD_FASTMAP;
-				kfree(ech);
-				goto fail;
-			}
-
-			err = ubi_io_read_ec_hdr(ubi, tmp_aeb->pnum, ech, 0);
-			if (err && err != UBI_IO_BITFLIPS) {
-				ubi_err("unable to read EC header! PEB:%i " \
-					"err:%i", tmp_aeb->pnum, err);
-				ret = err > 0 ? UBI_BAD_FASTMAP : err;
-				kfree(ech);
-
-				goto fail;
-			} else if (err == UBI_IO_BITFLIPS)
-				tmp_aeb->scrub = 1;
-
-			tmp_aeb->ec = be64_to_cpu(ech->ec);
-			assign_aeb_to_av(ai, tmp_aeb, av);
-		}
-
-		kfree(ech);
 	}
 
-	ret = scan_pool(ubi, ai, fmpl1->pebs, pool_size, &max_sqnum,
-			&eba_orphans, &freef);
+	ret = scan_pool(ubi, ai, fmpl->pebs, pool_size, &max_sqnum, &free);
 	if (ret)
 		goto fail;
 
-	ret = scan_pool(ubi, ai, fmpl2->pebs, wl_pool_size, &max_sqnum,
-			&eba_orphans, &freef);
+	ret = scan_pool(ubi, ai, fmpl_wl->pebs, wl_pool_size, &max_sqnum, &free);
 	if (ret)
 		goto fail;
 
 	if (max_sqnum > ai->max_sqnum)
 		ai->max_sqnum = max_sqnum;
 
-	list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &freef, u.list)
+	list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &free, u.list)
 		list_move_tail(&tmp_aeb->u.list, &ai->free);
 
-	ubi_assert(list_empty(&used));
-	ubi_assert(list_empty(&eba_orphans));
-	ubi_assert(list_empty(&freef));
+	list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &used, u.list)
+		list_move_tail(&tmp_aeb->u.list, &ai->erase);
+
+	ubi_assert(list_empty(&free));
 
 	/*
 	 * If fastmap is leaking PEBs (must not happen), raise a
@@ -865,14 +857,10 @@
 		list_del(&tmp_aeb->u.list);
 		kmem_cache_free(ai->aeb_slab_cache, tmp_aeb);
 	}
-	list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &eba_orphans, u.list) {
+	list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &free, u.list) {
 		list_del(&tmp_aeb->u.list);
 		kmem_cache_free(ai->aeb_slab_cache, tmp_aeb);
 	}
-	list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &freef, u.list) {
-		list_del(&tmp_aeb->u.list);
-		kmem_cache_free(ai->aeb_slab_cache, tmp_aeb);
-	}
 
 	return ret;
 }
@@ -899,7 +887,7 @@
 	__be32 crc, tmp_crc;
 	unsigned long long sqnum = 0;
 
-	mutex_lock(&ubi->fm_mutex);
+	down_write(&ubi->fm_protect);
 	memset(ubi->fm_buf, 0, ubi->fm_size);
 
 	fmsb = kmalloc(sizeof(*fmsb), GFP_KERNEL);
@@ -922,14 +910,14 @@
 		fm->to_be_tortured[0] = 1;
 
 	if (be32_to_cpu(fmsb->magic) != UBI_FM_SB_MAGIC) {
-		ubi_err("bad super block magic: 0x%x, expected: 0x%x",
+		ubi_err(ubi, "bad super block magic: 0x%x, expected: 0x%x",
 			be32_to_cpu(fmsb->magic), UBI_FM_SB_MAGIC);
 		ret = UBI_BAD_FASTMAP;
 		goto free_fm_sb;
 	}
 
 	if (fmsb->version != UBI_FM_FMT_VERSION) {
-		ubi_err("bad fastmap version: %i, expected: %i",
+		ubi_err(ubi, "bad fastmap version: %i, expected: %i",
 			fmsb->version, UBI_FM_FMT_VERSION);
 		ret = UBI_BAD_FASTMAP;
 		goto free_fm_sb;
@@ -937,15 +925,16 @@
 
 	used_blocks = be32_to_cpu(fmsb->used_blocks);
 	if (used_blocks > UBI_FM_MAX_BLOCKS || used_blocks < 1) {
-		ubi_err("number of fastmap blocks is invalid: %i", used_blocks);
+		ubi_err(ubi, "number of fastmap blocks is invalid: %i",
+			used_blocks);
 		ret = UBI_BAD_FASTMAP;
 		goto free_fm_sb;
 	}
 
 	fm_size = ubi->leb_size * used_blocks;
 	if (fm_size != ubi->fm_size) {
-		ubi_err("bad fastmap size: %zi, expected: %zi", fm_size,
-			ubi->fm_size);
+		ubi_err(ubi, "bad fastmap size: %zi, expected: %zi",
+			fm_size, ubi->fm_size);
 		ret = UBI_BAD_FASTMAP;
 		goto free_fm_sb;
 	}
@@ -974,7 +963,7 @@
 
 		ret = ubi_io_read_ec_hdr(ubi, pnum, ech, 0);
 		if (ret && ret != UBI_IO_BITFLIPS) {
-			ubi_err("unable to read fastmap block# %i EC (PEB: %i)",
+			ubi_err(ubi, "unable to read fastmap block# %i EC (PEB: %i)",
 				i, pnum);
 			if (ret > 0)
 				ret = UBI_BAD_FASTMAP;
@@ -991,7 +980,7 @@
 		 * we shouldn't fail if image_seq == 0.
 		 */
 		if (image_seq && (image_seq != ubi->image_seq)) {
-			ubi_err("wrong image seq:%d instead of %d",
+			ubi_err(ubi, "wrong image seq:%d instead of %d",
 				be32_to_cpu(ech->image_seq), ubi->image_seq);
 			ret = UBI_BAD_FASTMAP;
 			goto free_hdr;
@@ -999,15 +988,14 @@
 
 		ret = ubi_io_read_vid_hdr(ubi, pnum, vh, 0);
 		if (ret && ret != UBI_IO_BITFLIPS) {
-			ubi_err("unable to read fastmap block# %i (PEB: %i)",
+			ubi_err(ubi, "unable to read fastmap block# %i (PEB: %i)",
 				i, pnum);
 			goto free_hdr;
 		}
 
 		if (i == 0) {
 			if (be32_to_cpu(vh->vol_id) != UBI_FM_SB_VOLUME_ID) {
-				ubi_err("bad fastmap anchor vol_id: 0x%x," \
-					" expected: 0x%x",
+				ubi_err(ubi, "bad fastmap anchor vol_id: 0x%x, expected: 0x%x",
 					be32_to_cpu(vh->vol_id),
 					UBI_FM_SB_VOLUME_ID);
 				ret = UBI_BAD_FASTMAP;
@@ -1015,8 +1003,7 @@
 			}
 		} else {
 			if (be32_to_cpu(vh->vol_id) != UBI_FM_DATA_VOLUME_ID) {
-				ubi_err("bad fastmap data vol_id: 0x%x," \
-					" expected: 0x%x",
+				ubi_err(ubi, "bad fastmap data vol_id: 0x%x, expected: 0x%x",
 					be32_to_cpu(vh->vol_id),
 					UBI_FM_DATA_VOLUME_ID);
 				ret = UBI_BAD_FASTMAP;
@@ -1030,7 +1017,7 @@
 		ret = ubi_io_read(ubi, ubi->fm_buf + (ubi->leb_size * i), pnum,
 				  ubi->leb_start, ubi->leb_size);
 		if (ret && ret != UBI_IO_BITFLIPS) {
-			ubi_err("unable to read fastmap block# %i (PEB: %i, " \
+			ubi_err(ubi, "unable to read fastmap block# %i (PEB: %i, "
 				"err: %i)", i, pnum, ret);
 			goto free_hdr;
 		}
@@ -1044,8 +1031,9 @@
 	fmsb2->data_crc = 0;
 	crc = crc32(UBI_CRC32_INIT, ubi->fm_buf, fm_size);
 	if (crc != tmp_crc) {
-		ubi_err("fastmap data CRC is invalid");
-		ubi_err("CRC should be: 0x%x, calc: 0x%x", tmp_crc, crc);
+		ubi_err(ubi, "fastmap data CRC is invalid");
+		ubi_err(ubi, "CRC should be: 0x%x, calc: 0x%x",
+			tmp_crc, crc);
 		ret = UBI_BAD_FASTMAP;
 		goto free_hdr;
 	}
@@ -1081,17 +1069,18 @@
 	ubi->fm = fm;
 	ubi->fm_pool.max_size = ubi->fm->max_pool_size;
 	ubi->fm_wl_pool.max_size = ubi->fm->max_wl_pool_size;
-	ubi_msg("attached by fastmap");
-	ubi_msg("fastmap pool size: %d", ubi->fm_pool.max_size);
-	ubi_msg("fastmap WL pool size: %d", ubi->fm_wl_pool.max_size);
+	ubi_msg(ubi, "attached by fastmap");
+	ubi_msg(ubi, "fastmap pool size: %d", ubi->fm_pool.max_size);
+	ubi_msg(ubi, "fastmap WL pool size: %d",
+		ubi->fm_wl_pool.max_size);
 	ubi->fm_disabled = 0;
 
 	ubi_free_vid_hdr(ubi, vh);
 	kfree(ech);
 out:
-	mutex_unlock(&ubi->fm_mutex);
+	up_write(&ubi->fm_protect);
 	if (ret == UBI_BAD_FASTMAP)
-		ubi_err("Attach by fastmap failed, doing a full scan!");
+		ubi_err(ubi, "Attach by fastmap failed, doing a full scan!");
 	return ret;
 
 free_hdr:
@@ -1117,17 +1106,18 @@
 	void *fm_raw;
 	struct ubi_fm_sb *fmsb;
 	struct ubi_fm_hdr *fmh;
-	struct ubi_fm_scan_pool *fmpl1, *fmpl2;
+	struct ubi_fm_scan_pool *fmpl, *fmpl_wl;
 	struct ubi_fm_ec *fec;
 	struct ubi_fm_volhdr *fvh;
 	struct ubi_fm_eba *feba;
-	struct rb_node *node;
 	struct ubi_wl_entry *wl_e;
 	struct ubi_volume *vol;
 	struct ubi_vid_hdr *avhdr, *dvhdr;
 	struct ubi_work *ubi_wrk;
+	struct rb_node *tmp_rb;
 	int ret, i, j, free_peb_count, used_peb_count, vol_count;
 	int scrub_peb_count, erase_peb_count;
+	int *seen_pebs = NULL;
 
 	fm_raw = ubi->fm_buf;
 	memset(ubi->fm_buf, 0, ubi->fm_size);
@@ -1144,6 +1134,12 @@
 		goto out_kfree;
 	}
 
+	seen_pebs = init_seen(ubi);
+	if (IS_ERR(seen_pebs)) {
+		ret = PTR_ERR(seen_pebs);
+		goto out_kfree;
+	}
+
 	spin_lock(&ubi->volumes_lock);
 	spin_lock(&ubi->wl_lock);
 
@@ -1168,29 +1164,33 @@
 	erase_peb_count = 0;
 	vol_count = 0;
 
-	fmpl1 = (struct ubi_fm_scan_pool *)(fm_raw + fm_pos);
-	fm_pos += sizeof(*fmpl1);
-	fmpl1->magic = cpu_to_be32(UBI_FM_POOL_MAGIC);
-	fmpl1->size = cpu_to_be16(ubi->fm_pool.size);
-	fmpl1->max_size = cpu_to_be16(ubi->fm_pool.max_size);
+	fmpl = (struct ubi_fm_scan_pool *)(fm_raw + fm_pos);
+	fm_pos += sizeof(*fmpl);
+	fmpl->magic = cpu_to_be32(UBI_FM_POOL_MAGIC);
+	fmpl->size = cpu_to_be16(ubi->fm_pool.size);
+	fmpl->max_size = cpu_to_be16(ubi->fm_pool.max_size);
 
-	for (i = 0; i < ubi->fm_pool.size; i++)
-		fmpl1->pebs[i] = cpu_to_be32(ubi->fm_pool.pebs[i]);
+	for (i = 0; i < ubi->fm_pool.size; i++) {
+		fmpl->pebs[i] = cpu_to_be32(ubi->fm_pool.pebs[i]);
+		set_seen(ubi, ubi->fm_pool.pebs[i], seen_pebs);
+	}
 
-	fmpl2 = (struct ubi_fm_scan_pool *)(fm_raw + fm_pos);
-	fm_pos += sizeof(*fmpl2);
-	fmpl2->magic = cpu_to_be32(UBI_FM_POOL_MAGIC);
-	fmpl2->size = cpu_to_be16(ubi->fm_wl_pool.size);
-	fmpl2->max_size = cpu_to_be16(ubi->fm_wl_pool.max_size);
+	fmpl_wl = (struct ubi_fm_scan_pool *)(fm_raw + fm_pos);
+	fm_pos += sizeof(*fmpl_wl);
+	fmpl_wl->magic = cpu_to_be32(UBI_FM_POOL_MAGIC);
+	fmpl_wl->size = cpu_to_be16(ubi->fm_wl_pool.size);
+	fmpl_wl->max_size = cpu_to_be16(ubi->fm_wl_pool.max_size);
 
-	for (i = 0; i < ubi->fm_wl_pool.size; i++)
-		fmpl2->pebs[i] = cpu_to_be32(ubi->fm_wl_pool.pebs[i]);
+	for (i = 0; i < ubi->fm_wl_pool.size; i++) {
+		fmpl_wl->pebs[i] = cpu_to_be32(ubi->fm_wl_pool.pebs[i]);
+		set_seen(ubi, ubi->fm_wl_pool.pebs[i], seen_pebs);
+	}
 
-	for (node = rb_first(&ubi->free); node; node = rb_next(node)) {
-		wl_e = rb_entry(node, struct ubi_wl_entry, u.rb);
+	ubi_for_each_free_peb(ubi, wl_e, tmp_rb) {
 		fec = (struct ubi_fm_ec *)(fm_raw + fm_pos);
 
 		fec->pnum = cpu_to_be32(wl_e->pnum);
+		set_seen(ubi, wl_e->pnum, seen_pebs);
 		fec->ec = cpu_to_be32(wl_e->ec);
 
 		free_peb_count++;
@@ -1199,24 +1199,36 @@
 	}
 	fmh->free_peb_count = cpu_to_be32(free_peb_count);
 
-	for (node = rb_first(&ubi->used); node; node = rb_next(node)) {
-		wl_e = rb_entry(node, struct ubi_wl_entry, u.rb);
+	ubi_for_each_used_peb(ubi, wl_e, tmp_rb) {
 		fec = (struct ubi_fm_ec *)(fm_raw + fm_pos);
 
 		fec->pnum = cpu_to_be32(wl_e->pnum);
+		set_seen(ubi, wl_e->pnum, seen_pebs);
 		fec->ec = cpu_to_be32(wl_e->ec);
 
 		used_peb_count++;
 		fm_pos += sizeof(*fec);
 		ubi_assert(fm_pos <= ubi->fm_size);
 	}
+
+	ubi_for_each_protected_peb(ubi, i, wl_e) {
+		fec = (struct ubi_fm_ec *)(fm_raw + fm_pos);
+
+		fec->pnum = cpu_to_be32(wl_e->pnum);
+		set_seen(ubi, wl_e->pnum, seen_pebs);
+		fec->ec = cpu_to_be32(wl_e->ec);
+
+		used_peb_count++;
+		fm_pos += sizeof(*fec);
+		ubi_assert(fm_pos <= ubi->fm_size);
+	}
 	fmh->used_peb_count = cpu_to_be32(used_peb_count);
 
-	for (node = rb_first(&ubi->scrub); node; node = rb_next(node)) {
-		wl_e = rb_entry(node, struct ubi_wl_entry, u.rb);
+	ubi_for_each_scrub_peb(ubi, wl_e, tmp_rb) {
 		fec = (struct ubi_fm_ec *)(fm_raw + fm_pos);
 
 		fec->pnum = cpu_to_be32(wl_e->pnum);
+		set_seen(ubi, wl_e->pnum, seen_pebs);
 		fec->ec = cpu_to_be32(wl_e->ec);
 
 		scrub_peb_count++;
@@ -1234,6 +1246,7 @@
 			fec = (struct ubi_fm_ec *)(fm_raw + fm_pos);
 
 			fec->pnum = cpu_to_be32(wl_e->pnum);
+			set_seen(ubi, wl_e->pnum, seen_pebs);
 			fec->ec = cpu_to_be32(wl_e->ec);
 
 			erase_peb_count++;
@@ -1287,12 +1300,13 @@
 	dbg_bld("writing fastmap SB to PEB %i", new_fm->e[0]->pnum);
 	ret = ubi_io_write_vid_hdr(ubi, new_fm->e[0]->pnum, avhdr);
 	if (ret) {
-		ubi_err("unable to write vid_hdr to fastmap SB!");
+		ubi_err(ubi, "unable to write vid_hdr to fastmap SB!");
 		goto out_kfree;
 	}
 
 	for (i = 0; i < new_fm->used_blocks; i++) {
 		fmsb->block_loc[i] = cpu_to_be32(new_fm->e[i]->pnum);
+		set_seen(ubi, new_fm->e[i]->pnum, seen_pebs);
 		fmsb->block_ec[i] = cpu_to_be32(new_fm->e[i]->ec);
 	}
 
@@ -1307,7 +1321,7 @@
 			new_fm->e[i]->pnum, be64_to_cpu(dvhdr->sqnum));
 		ret = ubi_io_write_vid_hdr(ubi, new_fm->e[i]->pnum, dvhdr);
 		if (ret) {
-			ubi_err("unable to write vid_hdr to PEB %i!",
+			ubi_err(ubi, "unable to write vid_hdr to PEB %i!",
 				new_fm->e[i]->pnum);
 			goto out_kfree;
 		}
@@ -1317,7 +1331,7 @@
 		ret = ubi_io_write(ubi, fm_raw + (i * ubi->leb_size),
 			new_fm->e[i]->pnum, ubi->leb_start, ubi->leb_size);
 		if (ret) {
-			ubi_err("unable to write fastmap to PEB %i!",
+			ubi_err(ubi, "unable to write fastmap to PEB %i!",
 				new_fm->e[i]->pnum);
 			goto out_kfree;
 		}
@@ -1326,11 +1340,13 @@
 	ubi_assert(new_fm);
 	ubi->fm = new_fm;
 
+	ret = self_check_seen(ubi, seen_pebs);
 	dbg_bld("fastmap written!");
 
 out_kfree:
 	ubi_free_vid_hdr(ubi, avhdr);
 	ubi_free_vid_hdr(ubi, dvhdr);
+	free_seen(seen_pebs);
 out:
 	return ret;
 }
@@ -1385,31 +1401,87 @@
 /**
  * invalidate_fastmap - destroys a fastmap.
  * @ubi: UBI device object
- * @fm: the fastmap to be destroyed
  *
+ * This function ensures that upon next UBI attach a full scan
+ * is issued. We need this if UBI is about to write a new fastmap
+ * but is unable to do so. In this case we have two options:
+ * a) Make sure that the current fastmap will not be usued upon
+ * attach time and contine or b) fall back to RO mode to have the
+ * current fastmap in a valid state.
  * Returns 0 on success, < 0 indicates an internal error.
  */
-static int invalidate_fastmap(struct ubi_device *ubi,
-			      struct ubi_fastmap_layout *fm)
+static int invalidate_fastmap(struct ubi_device *ubi)
 {
 	int ret;
-	struct ubi_vid_hdr *vh;
+	struct ubi_fastmap_layout *fm;
+	struct ubi_wl_entry *e;
+	struct ubi_vid_hdr *vh = NULL;
 
-	ret = erase_block(ubi, fm->e[0]->pnum);
-	if (ret < 0)
-		return ret;
+	if (!ubi->fm)
+		return 0;
+
+	ubi->fm = NULL;
+
+	ret = -ENOMEM;
+	fm = kzalloc(sizeof(*fm), GFP_KERNEL);
+	if (!fm)
+		goto out;
 
 	vh = new_fm_vhdr(ubi, UBI_FM_SB_VOLUME_ID);
 	if (!vh)
-		return -ENOMEM;
+		goto out_free_fm;
 
-	/* deleting the current fastmap SB is not enough, an old SB may exist,
-	 * so create a (corrupted) SB such that fastmap will find it and fall
-	 * back to scanning mode in any case */
+	ret = -ENOSPC;
+	e = ubi_wl_get_fm_peb(ubi, 1);
+	if (!e)
+		goto out_free_fm;
+
+	/*
+	 * Create fake fastmap such that UBI will fall back
+	 * to scanning mode.
+	 */
 	vh->sqnum = cpu_to_be64(ubi_next_sqnum(ubi));
-	ret = ubi_io_write_vid_hdr(ubi, fm->e[0]->pnum, vh);
+	ret = ubi_io_write_vid_hdr(ubi, e->pnum, vh);
+	if (ret < 0) {
+		ubi_wl_put_fm_peb(ubi, e, 0, 0);
+		goto out_free_fm;
+	}
+
+	fm->used_blocks = 1;
+	fm->e[0] = e;
 
+	ubi->fm = fm;
+
+out:
+	ubi_free_vid_hdr(ubi, vh);
 	return ret;
+
+out_free_fm:
+	kfree(fm);
+	goto out;
+}
+
+/**
+ * return_fm_pebs - returns all PEBs used by a fastmap back to the
+ * WL sub-system.
+ * @ubi: UBI device object
+ * @fm: fastmap layout object
+ */
+static void return_fm_pebs(struct ubi_device *ubi,
+			   struct ubi_fastmap_layout *fm)
+{
+	int i;
+
+	if (!fm)
+		return;
+
+	for (i = 0; i < fm->used_blocks; i++) {
+		if (fm->e[i]) {
+			ubi_wl_put_fm_peb(ubi, fm->e[i], i,
+					  fm->to_be_tortured[i]);
+			fm->e[i] = NULL;
+		}
+	}
 }
 
 /**
@@ -1421,50 +1493,37 @@
  */
 int ubi_update_fastmap(struct ubi_device *ubi)
 {
-	int ret, i;
+	int ret, i, j;
 	struct ubi_fastmap_layout *new_fm, *old_fm;
 	struct ubi_wl_entry *tmp_e;
 
-	mutex_lock(&ubi->fm_mutex);
+	down_write(&ubi->fm_protect);
 
 	ubi_refill_pools(ubi);
 
 	if (ubi->ro_mode || ubi->fm_disabled) {
-		mutex_unlock(&ubi->fm_mutex);
+		up_write(&ubi->fm_protect);
 		return 0;
 	}
 
 	ret = ubi_ensure_anchor_pebs(ubi);
 	if (ret) {
-		mutex_unlock(&ubi->fm_mutex);
+		up_write(&ubi->fm_protect);
 		return ret;
 	}
 
 	new_fm = kzalloc(sizeof(*new_fm), GFP_KERNEL);
 	if (!new_fm) {
-		mutex_unlock(&ubi->fm_mutex);
+		up_write(&ubi->fm_protect);
 		return -ENOMEM;
 	}
 
 	new_fm->used_blocks = ubi->fm_size / ubi->leb_size;
-
-	for (i = 0; i < new_fm->used_blocks; i++) {
-		new_fm->e[i] = kmem_cache_alloc(ubi_wl_entry_slab, GFP_KERNEL);
-		if (!new_fm->e[i]) {
-			while (i--)
-				kfree(new_fm->e[i]);
-
-			kfree(new_fm);
-			mutex_unlock(&ubi->fm_mutex);
-			return -ENOMEM;
-		}
-	}
-
 	old_fm = ubi->fm;
 	ubi->fm = NULL;
 
 	if (new_fm->used_blocks > UBI_FM_MAX_BLOCKS) {
-		ubi_err("fastmap too large");
+		ubi_err(ubi, "fastmap too large");
 		ret = -ENOSPC;
 		goto err;
 	}
@@ -1474,40 +1533,52 @@
 		tmp_e = ubi_wl_get_fm_peb(ubi, 0);
 		spin_unlock(&ubi->wl_lock);
 
-		if (!tmp_e && !old_fm) {
-			int j;
-			ubi_err("could not get any free erase block");
-
-			for (j = 1; j < i; j++)
-				ubi_wl_put_fm_peb(ubi, new_fm->e[j], j, 0);
+		if (!tmp_e) {
+			if (old_fm && old_fm->e[i]) {
+				ret = erase_block(ubi, old_fm->e[i]->pnum);
+				if (ret < 0) {
+					ubi_err(ubi, "could not erase old fastmap PEB");
 
-			ret = -ENOSPC;
-			goto err;
-		} else if (!tmp_e && old_fm) {
-			ret = erase_block(ubi, old_fm->e[i]->pnum);
-			if (ret < 0) {
-				int j;
+					for (j = 1; j < i; j++) {
+						ubi_wl_put_fm_peb(ubi, new_fm->e[j],
+								  j, 0);
+						new_fm->e[j] = NULL;
+					}
+					goto err;
+				}
+				new_fm->e[i] = old_fm->e[i];
+				old_fm->e[i] = NULL;
+			} else {
+				ubi_err(ubi, "could not get any free erase block");
 
-				for (j = 1; j < i; j++)
-					ubi_wl_put_fm_peb(ubi, new_fm->e[j],
-							  j, 0);
+				for (j = 1; j < i; j++) {
+					ubi_wl_put_fm_peb(ubi, new_fm->e[j], j, 0);
+					new_fm->e[j] = NULL;
+				}
 
-				ubi_err("could not erase old fastmap PEB");
+				ret = -ENOSPC;
 				goto err;
 			}
-
-			new_fm->e[i]->pnum = old_fm->e[i]->pnum;
-			new_fm->e[i]->ec = old_fm->e[i]->ec;
 		} else {
-			new_fm->e[i]->pnum = tmp_e->pnum;
-			new_fm->e[i]->ec = tmp_e->ec;
+			new_fm->e[i] = tmp_e;
 
-			if (old_fm)
+			if (old_fm && old_fm->e[i]) {
 				ubi_wl_put_fm_peb(ubi, old_fm->e[i], i,
 						  old_fm->to_be_tortured[i]);
+				old_fm->e[i] = NULL;
+			}
 		}
 	}
 
+	/* Old fastmap is larger than the new one */
+	if (old_fm && new_fm->used_blocks < old_fm->used_blocks) {
+		for (i = new_fm->used_blocks; i < old_fm->used_blocks; i++) {
+			ubi_wl_put_fm_peb(ubi, old_fm->e[i], i,
+					  old_fm->to_be_tortured[i]);
+			old_fm->e[i] = NULL;
+		}
+	}
+
 	spin_lock(&ubi->wl_lock);
 	tmp_e = ubi_wl_get_fm_peb(ubi, 1);
 	spin_unlock(&ubi->wl_lock);
@@ -1517,67 +1588,67 @@
 		if (!tmp_e) {
 			ret = erase_block(ubi, old_fm->e[0]->pnum);
 			if (ret < 0) {
-				int i;
-				ubi_err("could not erase old anchor PEB");
+				ubi_err(ubi, "could not erase old anchor PEB");
 
-				for (i = 1; i < new_fm->used_blocks; i++)
+				for (i = 1; i < new_fm->used_blocks; i++) {
 					ubi_wl_put_fm_peb(ubi, new_fm->e[i],
 							  i, 0);
+					new_fm->e[i] = NULL;
+				}
 				goto err;
 			}
-
-			new_fm->e[0]->pnum = old_fm->e[0]->pnum;
+			new_fm->e[0] = old_fm->e[0];
 			new_fm->e[0]->ec = ret;
+			old_fm->e[0] = NULL;
 		} else {
 			/* we've got a new anchor PEB, return the old one */
 			ubi_wl_put_fm_peb(ubi, old_fm->e[0], 0,
 					  old_fm->to_be_tortured[0]);
-
-			new_fm->e[0]->pnum = tmp_e->pnum;
-			new_fm->e[0]->ec = tmp_e->ec;
+			new_fm->e[0] = tmp_e;
+			old_fm->e[0] = NULL;
 		}
 	} else {
 		if (!tmp_e) {
-			int i;
-			ubi_err("could not find any anchor PEB");
+			ubi_err(ubi, "could not find any anchor PEB");
 
-			for (i = 1; i < new_fm->used_blocks; i++)
+			for (i = 1; i < new_fm->used_blocks; i++) {
 				ubi_wl_put_fm_peb(ubi, new_fm->e[i], i, 0);
+				new_fm->e[i] = NULL;
+			}
 
 			ret = -ENOSPC;
 			goto err;
 		}
-
-		new_fm->e[0]->pnum = tmp_e->pnum;
-		new_fm->e[0]->ec = tmp_e->ec;
+		new_fm->e[0] = tmp_e;
 	}
 
 	down_write(&ubi->work_sem);
-	down_write(&ubi->fm_sem);
+	down_write(&ubi->fm_eba_sem);
 	ret = ubi_write_fastmap(ubi, new_fm);
-	up_write(&ubi->fm_sem);
+	up_write(&ubi->fm_eba_sem);
 	up_write(&ubi->work_sem);
 
 	if (ret)
 		goto err;
 
 out_unlock:
-	mutex_unlock(&ubi->fm_mutex);
+	up_write(&ubi->fm_protect);
 	kfree(old_fm);
 	return ret;
 
 err:
-	kfree(new_fm);
-
-	ubi_warn("Unable to write new fastmap, err=%i", ret);
+	ubi_warn(ubi, "Unable to write new fastmap, err=%i", ret);
 
-	ret = 0;
-	if (old_fm) {
-		ret = invalidate_fastmap(ubi, old_fm);
-		if (ret < 0)
-			ubi_err("Unable to invalidiate current fastmap!");
-		else if (ret)
-			ret = 0;
+	ret = invalidate_fastmap(ubi);
+	if (ret < 0) {
+		ubi_err(ubi, "Unable to invalidiate current fastmap!");
+		ubi_ro_mode(ubi);
+	} else {
+		return_fm_pebs(ubi, old_fm);
+		return_fm_pebs(ubi, new_fm);
+		ret = 0;
 	}
+
+	kfree(new_fm);
 	goto out_unlock;
 }
diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c
index 0e2e933..d1bdec3 100644
--- a/drivers/mtd/ubi/io.c
+++ b/drivers/mtd/ubi/io.c
@@ -169,19 +169,20 @@
 			 * enabled. A corresponding message will be printed
 			 * later, when it is has been scrubbed.
 			 */
-			ubi_msg("fixable bit-flip detected at PEB %d", pnum);
+			ubi_msg(ubi, "fixable bit-flip detected at PEB %d",
+				pnum);
 			ubi_assert(len == read);
 			return UBI_IO_BITFLIPS;
 		}
 
 		if (retries++ < UBI_IO_RETRIES) {
-			ubi_warn("error %d%s while reading %d bytes from PEB %d:%d, read only %zd bytes, retry",
+			ubi_warn(ubi, "error %d%s while reading %d bytes from PEB %d:%d, read only %zd bytes, retry",
 				 err, errstr, len, pnum, offset, read);
 			yield();
 			goto retry;
 		}
 
-		ubi_err("error %d%s while reading %d bytes from PEB %d:%d, read %zd bytes",
+		ubi_err(ubi, "error %d%s while reading %d bytes from PEB %d:%d, read %zd bytes",
 			err, errstr, len, pnum, offset, read);
 		dump_stack();
 
@@ -238,7 +239,7 @@
 	ubi_assert(len > 0 && len % ubi->hdrs_min_io_size == 0);
 
 	if (ubi->ro_mode) {
-		ubi_err("read-only mode");
+		ubi_err(ubi, "read-only mode");
 		return -EROFS;
 	}
 
@@ -265,7 +266,7 @@
 	}
 
 	if (ubi_dbg_is_write_failure(ubi)) {
-		ubi_err("cannot write %d bytes to PEB %d:%d (emulated)",
+		ubi_err(ubi, "cannot write %d bytes to PEB %d:%d (emulated)",
 			len, pnum, offset);
 		dump_stack();
 		return -EIO;
@@ -274,7 +275,7 @@
 	addr = (loff_t)pnum * ubi->peb_size + offset;
 	err = mtd_write(ubi->mtd, addr, len, &written, buf);
 	if (err) {
-		ubi_err("error %d while writing %d bytes to PEB %d:%d, written %zd bytes",
+		ubi_err(ubi, "error %d while writing %d bytes to PEB %d:%d, written %zd bytes",
 			err, len, pnum, offset, written);
 		dump_stack();
 		ubi_dump_flash(ubi, pnum, offset, len);
@@ -330,7 +331,7 @@
 	ubi_assert(pnum >= 0 && pnum < ubi->peb_count);
 
 	if (ubi->ro_mode) {
-		ubi_err("read-only mode");
+		ubi_err(ubi, "read-only mode");
 		return -EROFS;
 	}
 
@@ -347,12 +348,12 @@
 	err = mtd_erase(ubi->mtd, &ei);
 	if (err) {
 		if (retries++ < UBI_IO_RETRIES) {
-			ubi_warn("error %d while erasing PEB %d, retry",
+			ubi_warn(ubi, "error %d while erasing PEB %d, retry",
 				 err, pnum);
 			yield();
 			goto retry;
 		}
-		ubi_err("cannot erase PEB %d, error %d", pnum, err);
+		ubi_err(ubi, "cannot erase PEB %d, error %d", pnum, err);
 		dump_stack();
 		return err;
 	}
@@ -360,17 +361,18 @@
 	err = wait_event_interruptible(wq, ei.state == MTD_ERASE_DONE ||
 					   ei.state == MTD_ERASE_FAILED);
 	if (err) {
-		ubi_err("interrupted PEB %d erasure", pnum);
+		ubi_err(ubi, "interrupted PEB %d erasure", pnum);
 		return -EINTR;
 	}
 
 	if (ei.state == MTD_ERASE_FAILED) {
 		if (retries++ < UBI_IO_RETRIES) {
-			ubi_warn("error while erasing PEB %d, retry", pnum);
+			ubi_warn(ubi, "error while erasing PEB %d, retry",
+				 pnum);
 			yield();
 			goto retry;
 		}
-		ubi_err("cannot erase PEB %d", pnum);
+		ubi_err(ubi, "cannot erase PEB %d", pnum);
 		dump_stack();
 		return -EIO;
 	}
@@ -380,7 +382,7 @@
 		return err;
 
 	if (ubi_dbg_is_erase_failure(ubi)) {
-		ubi_err("cannot erase PEB %d (emulated)", pnum);
+		ubi_err(ubi, "cannot erase PEB %d (emulated)", pnum);
 		return -EIO;
 	}
 
@@ -403,7 +405,7 @@
 {
 	int err, i, patt_count;
 
-	ubi_msg("run torture test for PEB %d", pnum);
+	ubi_msg(ubi, "run torture test for PEB %d", pnum);
 	patt_count = ARRAY_SIZE(patterns);
 	ubi_assert(patt_count > 0);
 
@@ -420,7 +422,7 @@
 
 		err = ubi_check_pattern(ubi->peb_buf, 0xFF, ubi->peb_size);
 		if (err == 0) {
-			ubi_err("erased PEB %d, but a non-0xFF byte found",
+			ubi_err(ubi, "erased PEB %d, but a non-0xFF byte found",
 				pnum);
 			err = -EIO;
 			goto out;
@@ -440,7 +442,7 @@
 		err = ubi_check_pattern(ubi->peb_buf, patterns[i],
 					ubi->peb_size);
 		if (err == 0) {
-			ubi_err("pattern %x checking failed for PEB %d",
+			ubi_err(ubi, "pattern %x checking failed for PEB %d",
 				patterns[i], pnum);
 			err = -EIO;
 			goto out;
@@ -448,7 +450,7 @@
 	}
 
 	err = patt_count;
-	ubi_msg("PEB %d passed torture test, do not mark it as bad", pnum);
+	ubi_msg(ubi, "PEB %d passed torture test, do not mark it as bad", pnum);
 
 out:
 	mutex_unlock(&ubi->buf_mutex);
@@ -458,7 +460,7 @@
 		 * has not passed because it happened on a freshly erased
 		 * physical eraseblock which means something is wrong with it.
 		 */
-		ubi_err("read problems on freshly erased PEB %d, must be bad",
+		ubi_err(ubi, "read problems on freshly erased PEB %d, must be bad",
 			pnum);
 		err = -EIO;
 	}
@@ -534,7 +536,7 @@
 	 * it. Supposedly the flash media or the driver is screwed up, so
 	 * return an error.
 	 */
-	ubi_err("cannot invalidate PEB %d, write returned %d", pnum, err);
+	ubi_err(ubi, "cannot invalidate PEB %d, write returned %d", pnum, err);
 	ubi_dump_flash(ubi, pnum, 0, ubi->peb_size);
 	return -EIO;
 }
@@ -566,7 +568,7 @@
 		return err;
 
 	if (ubi->ro_mode) {
-		ubi_err("read-only mode");
+		ubi_err(ubi, "read-only mode");
 		return -EROFS;
 	}
 
@@ -608,7 +610,7 @@
 
 		ret = mtd_block_isbad(mtd, (loff_t)pnum * ubi->peb_size);
 		if (ret < 0)
-			ubi_err("error %d while checking if PEB %d is bad",
+			ubi_err(ubi, "error %d while checking if PEB %d is bad",
 				ret, pnum);
 		else if (ret)
 			dbg_io("PEB %d is bad", pnum);
@@ -634,7 +636,7 @@
 	ubi_assert(pnum >= 0 && pnum < ubi->peb_count);
 
 	if (ubi->ro_mode) {
-		ubi_err("read-only mode");
+		ubi_err(ubi, "read-only mode");
 		return -EROFS;
 	}
 
@@ -643,7 +645,7 @@
 
 	err = mtd_block_markbad(mtd, (loff_t)pnum * ubi->peb_size);
 	if (err)
-		ubi_err("cannot mark PEB %d bad, error %d", pnum, err);
+		ubi_err(ubi, "cannot mark PEB %d bad, error %d", pnum, err);
 	return err;
 }
 
@@ -666,32 +668,32 @@
 	leb_start = be32_to_cpu(ec_hdr->data_offset);
 
 	if (ec_hdr->version != UBI_VERSION) {
-		ubi_err("node with incompatible UBI version found: this UBI version is %d, image version is %d",
+		ubi_err(ubi, "node with incompatible UBI version found: this UBI version is %d, image version is %d",
 			UBI_VERSION, (int)ec_hdr->version);
 		goto bad;
 	}
 
 	if (vid_hdr_offset != ubi->vid_hdr_offset) {
-		ubi_err("bad VID header offset %d, expected %d",
+		ubi_err(ubi, "bad VID header offset %d, expected %d",
 			vid_hdr_offset, ubi->vid_hdr_offset);
 		goto bad;
 	}
 
 	if (leb_start != ubi->leb_start) {
-		ubi_err("bad data offset %d, expected %d",
+		ubi_err(ubi, "bad data offset %d, expected %d",
 			leb_start, ubi->leb_start);
 		goto bad;
 	}
 
 	if (ec < 0 || ec > UBI_MAX_ERASECOUNTER) {
-		ubi_err("bad erase counter %lld", ec);
+		ubi_err(ubi, "bad erase counter %lld", ec);
 		goto bad;
 	}
 
 	return 0;
 
 bad:
-	ubi_err("bad EC header");
+	ubi_err(ubi, "bad EC header");
 	ubi_dump_ec_hdr(ec_hdr);
 	dump_stack();
 	return 1;
@@ -757,7 +759,7 @@
 		if (ubi_check_pattern(ec_hdr, 0xFF, UBI_EC_HDR_SIZE)) {
 			/* The physical eraseblock is supposedly empty */
 			if (verbose)
-				ubi_warn("no EC header found at PEB %d, only 0xFF bytes",
+				ubi_warn(ubi, "no EC header found at PEB %d, only 0xFF bytes",
 					 pnum);
 			dbg_bld("no EC header found at PEB %d, only 0xFF bytes",
 				pnum);
@@ -772,7 +774,7 @@
 		 * 0xFF bytes. Report that the header is corrupted.
 		 */
 		if (verbose) {
-			ubi_warn("bad magic number at PEB %d: %08x instead of %08x",
+			ubi_warn(ubi, "bad magic number at PEB %d: %08x instead of %08x",
 				 pnum, magic, UBI_EC_HDR_MAGIC);
 			ubi_dump_ec_hdr(ec_hdr);
 		}
@@ -786,7 +788,7 @@
 
 	if (hdr_crc != crc) {
 		if (verbose) {
-			ubi_warn("bad EC header CRC at PEB %d, calculated %#08x, read %#08x",
+			ubi_warn(ubi, "bad EC header CRC at PEB %d, calculated %#08x, read %#08x",
 				 pnum, crc, hdr_crc);
 			ubi_dump_ec_hdr(ec_hdr);
 		}
@@ -802,7 +804,7 @@
 	/* And of course validate what has just been read from the media */
 	err = validate_ec_hdr(ubi, ec_hdr);
 	if (err) {
-		ubi_err("validation failed for PEB %d", pnum);
+		ubi_err(ubi, "validation failed for PEB %d", pnum);
 		return -EINVAL;
 	}
 
@@ -849,6 +851,9 @@
 	if (err)
 		return err;
 
+	if (ubi_dbg_power_cut(ubi, POWER_CUT_EC_WRITE))
+		return -EROFS;
+
 	err = ubi_io_write(ubi, ec_hdr, pnum, 0, ubi->ec_hdr_alsize);
 	return err;
 }
@@ -876,40 +881,40 @@
 	int usable_leb_size = ubi->leb_size - data_pad;
 
 	if (copy_flag != 0 && copy_flag != 1) {
-		ubi_err("bad copy_flag");
+		ubi_err(ubi, "bad copy_flag");
 		goto bad;
 	}
 
 	if (vol_id < 0 || lnum < 0 || data_size < 0 || used_ebs < 0 ||
 	    data_pad < 0) {
-		ubi_err("negative values");
+		ubi_err(ubi, "negative values");
 		goto bad;
 	}
 
 	if (vol_id >= UBI_MAX_VOLUMES && vol_id < UBI_INTERNAL_VOL_START) {
-		ubi_err("bad vol_id");
+		ubi_err(ubi, "bad vol_id");
 		goto bad;
 	}
 
 	if (vol_id < UBI_INTERNAL_VOL_START && compat != 0) {
-		ubi_err("bad compat");
+		ubi_err(ubi, "bad compat");
 		goto bad;
 	}
 
 	if (vol_id >= UBI_INTERNAL_VOL_START && compat != UBI_COMPAT_DELETE &&
 	    compat != UBI_COMPAT_RO && compat != UBI_COMPAT_PRESERVE &&
 	    compat != UBI_COMPAT_REJECT) {
-		ubi_err("bad compat");
+		ubi_err(ubi, "bad compat");
 		goto bad;
 	}
 
 	if (vol_type != UBI_VID_DYNAMIC && vol_type != UBI_VID_STATIC) {
-		ubi_err("bad vol_type");
+		ubi_err(ubi, "bad vol_type");
 		goto bad;
 	}
 
 	if (data_pad >= ubi->leb_size / 2) {
-		ubi_err("bad data_pad");
+		ubi_err(ubi, "bad data_pad");
 		goto bad;
 	}
 
@@ -921,45 +926,45 @@
 		 * mapped logical eraseblocks.
 		 */
 		if (used_ebs == 0) {
-			ubi_err("zero used_ebs");
+			ubi_err(ubi, "zero used_ebs");
 			goto bad;
 		}
 		if (data_size == 0) {
-			ubi_err("zero data_size");
+			ubi_err(ubi, "zero data_size");
 			goto bad;
 		}
 		if (lnum < used_ebs - 1) {
 			if (data_size != usable_leb_size) {
-				ubi_err("bad data_size");
+				ubi_err(ubi, "bad data_size");
 				goto bad;
 			}
 		} else if (lnum == used_ebs - 1) {
 			if (data_size == 0) {
-				ubi_err("bad data_size at last LEB");
+				ubi_err(ubi, "bad data_size at last LEB");
 				goto bad;
 			}
 		} else {
-			ubi_err("too high lnum");
+			ubi_err(ubi, "too high lnum");
 			goto bad;
 		}
 	} else {
 		if (copy_flag == 0) {
 			if (data_crc != 0) {
-				ubi_err("non-zero data CRC");
+				ubi_err(ubi, "non-zero data CRC");
 				goto bad;
 			}
 			if (data_size != 0) {
-				ubi_err("non-zero data_size");
+				ubi_err(ubi, "non-zero data_size");
 				goto bad;
 			}
 		} else {
 			if (data_size == 0) {
-				ubi_err("zero data_size of copy");
+				ubi_err(ubi, "zero data_size of copy");
 				goto bad;
 			}
 		}
 		if (used_ebs != 0) {
-			ubi_err("bad used_ebs");
+			ubi_err(ubi, "bad used_ebs");
 			goto bad;
 		}
 	}
@@ -967,7 +972,7 @@
 	return 0;
 
 bad:
-	ubi_err("bad VID header");
+	ubi_err(ubi, "bad VID header");
 	ubi_dump_vid_hdr(vid_hdr);
 	dump_stack();
 	return 1;
@@ -1012,7 +1017,7 @@
 
 		if (ubi_check_pattern(vid_hdr, 0xFF, UBI_VID_HDR_SIZE)) {
 			if (verbose)
-				ubi_warn("no VID header found at PEB %d, only 0xFF bytes",
+				ubi_warn(ubi, "no VID header found at PEB %d, only 0xFF bytes",
 					 pnum);
 			dbg_bld("no VID header found at PEB %d, only 0xFF bytes",
 				pnum);
@@ -1023,7 +1028,7 @@
 		}
 
 		if (verbose) {
-			ubi_warn("bad magic number at PEB %d: %08x instead of %08x",
+			ubi_warn(ubi, "bad magic number at PEB %d: %08x instead of %08x",
 				 pnum, magic, UBI_VID_HDR_MAGIC);
 			ubi_dump_vid_hdr(vid_hdr);
 		}
@@ -1037,7 +1042,7 @@
 
 	if (hdr_crc != crc) {
 		if (verbose) {
-			ubi_warn("bad CRC at PEB %d, calculated %#08x, read %#08x",
+			ubi_warn(ubi, "bad CRC at PEB %d, calculated %#08x, read %#08x",
 				 pnum, crc, hdr_crc);
 			ubi_dump_vid_hdr(vid_hdr);
 		}
@@ -1051,7 +1056,7 @@
 
 	err = validate_vid_hdr(ubi, vid_hdr);
 	if (err) {
-		ubi_err("validation failed for PEB %d", pnum);
+		ubi_err(ubi, "validation failed for PEB %d", pnum);
 		return -EINVAL;
 	}
 
@@ -1096,6 +1101,9 @@
 	if (err)
 		return err;
 
+	if (ubi_dbg_power_cut(ubi, POWER_CUT_VID_WRITE))
+		return -EROFS;
+
 	p = (char *)vid_hdr - ubi->vid_hdr_shift;
 	err = ubi_io_write(ubi, p, pnum, ubi->vid_hdr_aloffset,
 			   ubi->vid_hdr_alsize);
@@ -1121,7 +1129,7 @@
 	if (!err)
 		return err;
 
-	ubi_err("self-check failed for PEB %d", pnum);
+	ubi_err(ubi, "self-check failed for PEB %d", pnum);
 	dump_stack();
 	return err > 0 ? -EINVAL : err;
 }
@@ -1146,14 +1154,14 @@
 
 	magic = be32_to_cpu(ec_hdr->magic);
 	if (magic != UBI_EC_HDR_MAGIC) {
-		ubi_err("bad magic %#08x, must be %#08x",
+		ubi_err(ubi, "bad magic %#08x, must be %#08x",
 			magic, UBI_EC_HDR_MAGIC);
 		goto fail;
 	}
 
 	err = validate_ec_hdr(ubi, ec_hdr);
 	if (err) {
-		ubi_err("self-check failed for PEB %d", pnum);
+		ubi_err(ubi, "self-check failed for PEB %d", pnum);
 		goto fail;
 	}
 
@@ -1193,8 +1201,9 @@
 	crc = crc32(UBI_CRC32_INIT, ec_hdr, UBI_EC_HDR_SIZE_CRC);
 	hdr_crc = be32_to_cpu(ec_hdr->hdr_crc);
 	if (hdr_crc != crc) {
-		ubi_err("bad CRC, calculated %#08x, read %#08x", crc, hdr_crc);
-		ubi_err("self-check failed for PEB %d", pnum);
+		ubi_err(ubi, "bad CRC, calculated %#08x, read %#08x",
+			crc, hdr_crc);
+		ubi_err(ubi, "self-check failed for PEB %d", pnum);
 		ubi_dump_ec_hdr(ec_hdr);
 		dump_stack();
 		err = -EINVAL;
@@ -1228,21 +1237,21 @@
 
 	magic = be32_to_cpu(vid_hdr->magic);
 	if (magic != UBI_VID_HDR_MAGIC) {
-		ubi_err("bad VID header magic %#08x at PEB %d, must be %#08x",
+		ubi_err(ubi, "bad VID header magic %#08x at PEB %d, must be %#08x",
 			magic, pnum, UBI_VID_HDR_MAGIC);
 		goto fail;
 	}
 
 	err = validate_vid_hdr(ubi, vid_hdr);
 	if (err) {
-		ubi_err("self-check failed for PEB %d", pnum);
+		ubi_err(ubi, "self-check failed for PEB %d", pnum);
 		goto fail;
 	}
 
 	return err;
 
 fail:
-	ubi_err("self-check failed for PEB %d", pnum);
+	ubi_err(ubi, "self-check failed for PEB %d", pnum);
 	ubi_dump_vid_hdr(vid_hdr);
 	dump_stack();
 	return -EINVAL;
@@ -1280,9 +1289,9 @@
 	crc = crc32(UBI_CRC32_INIT, vid_hdr, UBI_EC_HDR_SIZE_CRC);
 	hdr_crc = be32_to_cpu(vid_hdr->hdr_crc);
 	if (hdr_crc != crc) {
-		ubi_err("bad VID header CRC at PEB %d, calculated %#08x, read %#08x",
+		ubi_err(ubi, "bad VID header CRC at PEB %d, calculated %#08x, read %#08x",
 			pnum, crc, hdr_crc);
-		ubi_err("self-check failed for PEB %d", pnum);
+		ubi_err(ubi, "self-check failed for PEB %d", pnum);
 		ubi_dump_vid_hdr(vid_hdr);
 		dump_stack();
 		err = -EINVAL;
@@ -1321,7 +1330,7 @@
 
 	buf1 = __vmalloc(len, GFP_NOFS, PAGE_KERNEL);
 	if (!buf1) {
-		ubi_err("cannot allocate memory to check writes");
+		ubi_err(ubi, "cannot allocate memory to check writes");
 		return 0;
 	}
 
@@ -1339,14 +1348,15 @@
 		if (c == c1)
 			continue;
 
-		ubi_err("self-check failed for PEB %d:%d, len %d",
+		ubi_err(ubi, "self-check failed for PEB %d:%d, len %d",
 			pnum, offset, len);
-		ubi_msg("data differ at position %d", i);
-		ubi_msg("hex dump of the original buffer from %d to %d",
+		ubi_msg(ubi, "data differ at position %d", i);
+		dump_len = max_t(int, 128, len - i);
+		ubi_msg(ubi, "hex dump of the original buffer from %d to %d",
 			i, i + dump_len);
 		print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
 			       buf + i, dump_len, 1);
-		ubi_msg("hex dump of the read buffer from %d to %d",
+		ubi_msg(ubi, "hex dump of the read buffer from %d to %d",
 			i, i + dump_len);
 		print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
 			       buf1 + i, dump_len, 1);
@@ -1386,20 +1396,20 @@
 
 	buf = __vmalloc(len, GFP_NOFS, PAGE_KERNEL);
 	if (!buf) {
-		ubi_err("cannot allocate memory to check for 0xFFs");
+		ubi_err(ubi, "cannot allocate memory to check for 0xFFs");
 		return 0;
 	}
 
 	err = mtd_read(ubi->mtd, addr, len, &read, buf);
 	if (err && !mtd_is_bitflip(err)) {
-		ubi_err("error %d while reading %d bytes from PEB %d:%d, read %zd bytes",
+		ubi_err(ubi, "err %d while reading %d bytes from PEB %d:%d, read %zd bytes",
 			err, len, pnum, offset, read);
 		goto error;
 	}
 
 	err = ubi_check_pattern(buf, 0xFF, len);
 	if (err == 0) {
-		ubi_err("flash region at PEB %d:%d, length %d does not contain all 0xFF bytes",
+		ubi_err(ubi, "flash region at PEB %d:%d, length %d does not contain all 0xFF bytes",
 			pnum, offset, len);
 		goto fail;
 	}
@@ -1408,8 +1418,8 @@
 	return 0;
 
 fail:
-	ubi_err("self-check failed for PEB %d", pnum);
-	ubi_msg("hex dump of the %d-%d region", offset, offset + len);
+	ubi_err(ubi, "self-check failed for PEB %d", pnum);
+	ubi_msg(ubi, "hex dump of the %d-%d region", offset, offset + len);
 	print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, buf, len, 1);
 	err = -EINVAL;
 error:
diff --git a/drivers/mtd/ubi/kapi.c b/drivers/mtd/ubi/kapi.c
index fd2bbd6..06b9314 100644
--- a/drivers/mtd/ubi/kapi.c
+++ b/drivers/mtd/ubi/kapi.c
@@ -132,7 +132,7 @@
 		return ERR_PTR(-EINVAL);
 
 	if (mode != UBI_READONLY && mode != UBI_READWRITE &&
-	    mode != UBI_EXCLUSIVE)
+	    mode != UBI_EXCLUSIVE && mode != UBI_METAONLY)
 		return ERR_PTR(-EINVAL);
 
 	/*
@@ -177,10 +177,17 @@
 		break;
 
 	case UBI_EXCLUSIVE:
-		if (vol->exclusive || vol->writers || vol->readers)
+		if (vol->exclusive || vol->writers || vol->readers ||
+		    vol->metaonly)
 			goto out_unlock;
 		vol->exclusive = 1;
 		break;
+
+	case UBI_METAONLY:
+		if (vol->metaonly || vol->exclusive)
+			goto out_unlock;
+		vol->metaonly = 1;
+		break;
 	}
 	get_device(&vol->dev);
 	vol->ref_count += 1;
@@ -199,7 +206,7 @@
 			return ERR_PTR(err);
 		}
 		if (err == 1) {
-			ubi_warn("volume %d on UBI device %d is corrupted",
+			ubi_warn(ubi, "volume %d on UBI device %d is corrupted",
 				 vol_id, ubi->ubi_num);
 			vol->corrupted = 1;
 		}
@@ -216,7 +223,7 @@
 	kfree(desc);
 out_put_ubi:
 	ubi_put_device(ubi);
-	ubi_err("cannot open device %d, volume %d, error %d",
+	ubi_err(ubi, "cannot open device %d, volume %d, error %d",
 		ubi_num, vol_id, err);
 	return ERR_PTR(err);
 }
@@ -303,7 +310,7 @@
 	if (error)
 		return ERR_PTR(error);
 
-	inode = path.dentry->d_inode;
+	inode = d_backing_inode(path.dentry);
 	mod = inode->i_mode;
 	ubi_num = ubi_major2num(imajor(inode));
 	vol_id = iminor(inode) - 1;
@@ -340,6 +347,10 @@
 		break;
 	case UBI_EXCLUSIVE:
 		vol->exclusive = 0;
+		break;
+	case UBI_METAONLY:
+		vol->metaonly = 0;
+		break;
 	}
 	vol->ref_count -= 1;
 	spin_unlock(&ubi->volumes_lock);
@@ -352,6 +363,43 @@
 EXPORT_SYMBOL_GPL(ubi_close_volume);
 
 /**
+ * leb_read_sanity_check - does sanity checks on read requests.
+ * @desc: volume descriptor
+ * @lnum: logical eraseblock number to read from
+ * @offset: offset within the logical eraseblock to read from
+ * @len: how many bytes to read
+ *
+ * This function is used by ubi_leb_read() and ubi_leb_read_sg()
+ * to perform sanity checks.
+ */
+static int leb_read_sanity_check(struct ubi_volume_desc *desc, int lnum,
+				 int offset, int len)
+{
+	struct ubi_volume *vol = desc->vol;
+	struct ubi_device *ubi = vol->ubi;
+	int vol_id = vol->vol_id;
+
+	if (vol_id < 0 || vol_id >= ubi->vtbl_slots || lnum < 0 ||
+	    lnum >= vol->used_ebs || offset < 0 || len < 0 ||
+	    offset + len > vol->usable_leb_size)
+		return -EINVAL;
+
+	if (vol->vol_type == UBI_STATIC_VOLUME) {
+		if (vol->used_ebs == 0)
+			/* Empty static UBI volume */
+			return 0;
+		if (lnum == vol->used_ebs - 1 &&
+		    offset + len > vol->last_eb_bytes)
+			return -EINVAL;
+	}
+
+	if (vol->upd_marker)
+		return -EBADF;
+
+	return 0;
+}
+
+/**
  * ubi_leb_read - read data.
  * @desc: volume descriptor
  * @lnum: logical eraseblock number to read from
@@ -387,28 +435,16 @@
 
 	dbg_gen("read %d bytes from LEB %d:%d:%d", len, vol_id, lnum, offset);
 
-	if (vol_id < 0 || vol_id >= ubi->vtbl_slots || lnum < 0 ||
-	    lnum >= vol->used_ebs || offset < 0 || len < 0 ||
-	    offset + len > vol->usable_leb_size)
-		return -EINVAL;
+	err = leb_read_sanity_check(desc, lnum, offset, len);
+	if (err < 0)
+		return err;
 
-	if (vol->vol_type == UBI_STATIC_VOLUME) {
-		if (vol->used_ebs == 0)
-			/* Empty static UBI volume */
-			return 0;
-		if (lnum == vol->used_ebs - 1 &&
-		    offset + len > vol->last_eb_bytes)
-			return -EINVAL;
-	}
-
-	if (vol->upd_marker)
-		return -EBADF;
 	if (len == 0)
 		return 0;
 
 	err = ubi_eba_read_leb(ubi, vol, lnum, buf, offset, len, check);
 	if (err && mtd_is_eccerr(err) && vol->vol_type == UBI_STATIC_VOLUME) {
-		ubi_warn("mark volume %d as corrupted", vol_id);
+		ubi_warn(ubi, "mark volume %d as corrupted", vol_id);
 		vol->corrupted = 1;
 	}
 
@@ -416,6 +452,47 @@
 }
 EXPORT_SYMBOL_GPL(ubi_leb_read);
 
+#ifndef __UBOOT__
+/**
+ * ubi_leb_read_sg - read data into a scatter gather list.
+ * @desc: volume descriptor
+ * @lnum: logical eraseblock number to read from
+ * @buf: buffer where to store the read data
+ * @offset: offset within the logical eraseblock to read from
+ * @len: how many bytes to read
+ * @check: whether UBI has to check the read data's CRC or not.
+ *
+ * This function works exactly like ubi_leb_read_sg(). But instead of
+ * storing the read data into a buffer it writes to an UBI scatter gather
+ * list.
+ */
+int ubi_leb_read_sg(struct ubi_volume_desc *desc, int lnum, struct ubi_sgl *sgl,
+		    int offset, int len, int check)
+{
+	struct ubi_volume *vol = desc->vol;
+	struct ubi_device *ubi = vol->ubi;
+	int err, vol_id = vol->vol_id;
+
+	dbg_gen("read %d bytes from LEB %d:%d:%d", len, vol_id, lnum, offset);
+
+	err = leb_read_sanity_check(desc, lnum, offset, len);
+	if (err < 0)
+		return err;
+
+	if (len == 0)
+		return 0;
+
+	err = ubi_eba_read_leb_sg(ubi, vol, sgl, lnum, offset, len, check);
+	if (err && mtd_is_eccerr(err) && vol->vol_type == UBI_STATIC_VOLUME) {
+		ubi_warn(ubi, "mark volume %d as corrupted", vol_id);
+		vol->corrupted = 1;
+	}
+
+	return err;
+}
+EXPORT_SYMBOL_GPL(ubi_leb_read_sg);
+#endif
+
 /**
  * ubi_leb_write - write data.
  * @desc: volume descriptor
diff --git a/drivers/mtd/ubi/misc.c b/drivers/mtd/ubi/misc.c
index 49530b7..504865b 100644
--- a/drivers/mtd/ubi/misc.c
+++ b/drivers/mtd/ubi/misc.c
@@ -63,6 +63,8 @@
 	for (i = 0; i < vol->used_ebs; i++) {
 		int size;
 
+		cond_resched();
+
 		if (i == vol->used_ebs - 1)
 			size = vol->last_eb_bytes;
 		else
@@ -100,7 +102,7 @@
 	ubi->avail_pebs -= need;
 	ubi->rsvd_pebs += need;
 	ubi->beb_rsvd_pebs += need;
-	ubi_msg("reserved more %d PEBs for bad PEB handling", need);
+	ubi_msg(ubi, "reserved more %d PEBs for bad PEB handling", need);
 }
 
 /**
@@ -117,7 +119,7 @@
 	ubi->beb_rsvd_level = ubi->bad_peb_limit - ubi->bad_peb_count;
 	if (ubi->beb_rsvd_level < 0) {
 		ubi->beb_rsvd_level = 0;
-		ubi_warn("number of bad PEBs (%d) is above the expected limit (%d), not reserving any PEBs for bad PEB handling, will use available PEBs (if any)",
+		ubi_warn(ubi, "number of bad PEBs (%d) is above the expected limit (%d), not reserving any PEBs for bad PEB handling, will use available PEBs (if any)",
 			 ubi->bad_peb_count, ubi->bad_peb_limit);
 	}
 }
diff --git a/drivers/mtd/ubi/ubi-media.h b/drivers/mtd/ubi/ubi-media.h
index 2809805..83345cd 100644
--- a/drivers/mtd/ubi/ubi-media.h
+++ b/drivers/mtd/ubi/ubi-media.h
@@ -395,8 +395,6 @@
 #define UBI_FM_MIN_POOL_SIZE	8
 #define UBI_FM_MAX_POOL_SIZE	256
 
-#define UBI_FM_WL_POOL_SIZE	25
-
 /**
  * struct ubi_fm_sb - UBI fastmap super block
  * @magic: fastmap super block magic number (%UBI_FM_SB_MAGIC)
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index 754b337..540f721 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -43,17 +43,18 @@
 
 /* Normal UBI messages */
 #ifdef CONFIG_UBI_SILENCE_MSG
-#define ubi_msg(fmt, ...)
+#define ubi_msg(ubi, fmt, ...)
 #else
-#define ubi_msg(fmt, ...) printk(KERN_NOTICE "UBI: " fmt "\n", ##__VA_ARGS__)
+#define ubi_msg(ubi, fmt, ...) printk(UBI_NAME_STR "%d: " fmt "\n", \
+					 ubi->ubi_num, ##__VA_ARGS__)
 #endif
 
 /* UBI warning messages */
-#define ubi_warn(fmt, ...) pr_warn("UBI warning: %s: " fmt "\n",  \
-				   __func__, ##__VA_ARGS__)
+#define ubi_warn(ubi, fmt, ...) pr_warn(UBI_NAME_STR "%d warning: %s: " fmt "\n", \
+					ubi->ubi_num, __func__, ##__VA_ARGS__)
 /* UBI error messages */
-#define ubi_err(fmt, ...) pr_err("UBI error: %s: " fmt "\n",      \
-				 __func__, ##__VA_ARGS__)
+#define ubi_err(ubi, fmt, ...) pr_err(UBI_NAME_STR "%d error: %s: " fmt "\n", \
+				      ubi->ubi_num, __func__, ##__VA_ARGS__)
 
 /* Background thread name pattern */
 #define UBI_BGT_NAME_PATTERN "ubi_bgt%dd"
@@ -147,6 +148,17 @@
 	UBI_BAD_FASTMAP,
 };
 
+/*
+ * Flags for emulate_power_cut in ubi_debug_info
+ *
+ * POWER_CUT_EC_WRITE: Emulate a power cut when writing an EC header
+ * POWER_CUT_VID_WRITE: Emulate a power cut when writing a VID header
+ */
+enum {
+	POWER_CUT_EC_WRITE = 0x01,
+	POWER_CUT_VID_WRITE = 0x02,
+};
+
 /**
  * struct ubi_wl_entry - wear-leveling entry.
  * @u.rb: link in the corresponding (free/used) RB-tree
@@ -257,6 +269,7 @@
  * @readers: number of users holding this volume in read-only mode
  * @writers: number of users holding this volume in read-write mode
  * @exclusive: whether somebody holds this volume in exclusive mode
+ * @metaonly: whether somebody is altering only meta data of this volume
  *
  * @reserved_pebs: how many physical eraseblocks are reserved for this volume
  * @vol_type: volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME)
@@ -305,6 +318,7 @@
 	int readers;
 	int writers;
 	int exclusive;
+	int metaonly;
 
 	int reserved_pebs;
 	int vol_type;
@@ -339,7 +353,8 @@
 /**
  * struct ubi_volume_desc - UBI volume descriptor returned when it is opened.
  * @vol: reference to the corresponding volume description object
- * @mode: open mode (%UBI_READONLY, %UBI_READWRITE, or %UBI_EXCLUSIVE)
+ * @mode: open mode (%UBI_READONLY, %UBI_READWRITE, %UBI_EXCLUSIVE
+ * or %UBI_METAONLY)
  */
 struct ubi_volume_desc {
 	struct ubi_volume *vol;
@@ -353,30 +368,48 @@
  *
  * @chk_gen: if UBI general extra checks are enabled
  * @chk_io: if UBI I/O extra checks are enabled
+ * @chk_fastmap: if UBI fastmap extra checks are enabled
  * @disable_bgt: disable the background task for testing purposes
  * @emulate_bitflips: emulate bit-flips for testing purposes
  * @emulate_io_failures: emulate write/erase failures for testing purposes
+ * @emulate_power_cut: emulate power cut for testing purposes
+ * @power_cut_counter: count down for writes left until emulated power cut
+ * @power_cut_min: minimum number of writes before emulating a power cut
+ * @power_cut_max: maximum number of writes until emulating a power cut
  * @dfs_dir_name: name of debugfs directory containing files of this UBI device
  * @dfs_dir: direntry object of the UBI device debugfs directory
  * @dfs_chk_gen: debugfs knob to enable UBI general extra checks
  * @dfs_chk_io: debugfs knob to enable UBI I/O extra checks
+ * @dfs_chk_fastmap: debugfs knob to enable UBI fastmap extra checks
  * @dfs_disable_bgt: debugfs knob to disable the background task
  * @dfs_emulate_bitflips: debugfs knob to emulate bit-flips
  * @dfs_emulate_io_failures: debugfs knob to emulate write/erase failures
+ * @dfs_emulate_power_cut: debugfs knob to emulate power cuts
+ * @dfs_power_cut_min: debugfs knob for minimum writes before power cut
+ * @dfs_power_cut_max: debugfs knob for maximum writes until power cut
  */
 struct ubi_debug_info {
 	unsigned int chk_gen:1;
 	unsigned int chk_io:1;
+	unsigned int chk_fastmap:1;
 	unsigned int disable_bgt:1;
 	unsigned int emulate_bitflips:1;
 	unsigned int emulate_io_failures:1;
+	unsigned int emulate_power_cut:2;
+	unsigned int power_cut_counter;
+	unsigned int power_cut_min;
+	unsigned int power_cut_max;
 	char dfs_dir_name[UBI_DFS_DIR_LEN + 1];
 	struct dentry *dfs_dir;
 	struct dentry *dfs_chk_gen;
 	struct dentry *dfs_chk_io;
+	struct dentry *dfs_chk_fastmap;
 	struct dentry *dfs_disable_bgt;
 	struct dentry *dfs_emulate_bitflips;
 	struct dentry *dfs_emulate_io_failures;
+	struct dentry *dfs_emulate_power_cut;
+	struct dentry *dfs_power_cut_min;
+	struct dentry *dfs_power_cut_max;
 };
 
 /**
@@ -390,7 +423,8 @@
  * @volumes_lock: protects @volumes, @rsvd_pebs, @avail_pebs, beb_rsvd_pebs,
  *                @beb_rsvd_level, @bad_peb_count, @good_peb_count, @vol_count,
  *                @vol->readers, @vol->writers, @vol->exclusive,
- *                @vol->ref_count, @vol->mapping and @vol->eba_tbl.
+ *                @vol->metaonly, @vol->ref_count, @vol->mapping and
+ *                @vol->eba_tbl.
  * @ref_count: count of references on the UBI device
  * @image_seq: image sequence number recorded on EC headers
  *
@@ -422,11 +456,13 @@
  * @fm_pool: in-memory data structure of the fastmap pool
  * @fm_wl_pool: in-memory data structure of the fastmap pool used by the WL
  *		sub-system
- * @fm_mutex: serializes ubi_update_fastmap() and protects @fm_buf
+ * @fm_protect: serializes ubi_update_fastmap(), protects @fm_buf and makes sure
+ * that critical sections cannot be interrupted by ubi_update_fastmap()
  * @fm_buf: vmalloc()'d buffer which holds the raw fastmap
  * @fm_size: fastmap size in bytes
- * @fm_sem: allows ubi_update_fastmap() to block EBA table changes
+ * @fm_eba_sem: allows ubi_update_fastmap() to block EBA table changes
  * @fm_work: fastmap work queue
+ * @fm_work_scheduled: non-zero if fastmap work was scheduled
  *
  * @used: RB-tree of used physical eraseblocks
  * @erroneous: RB-tree of erroneous used physical eraseblocks
@@ -438,9 +474,11 @@
  * @pq_head: protection queue head
  * @wl_lock: protects the @used, @free, @pq, @pq_head, @lookuptbl, @move_from,
  *	     @move_to, @move_to_put @erase_pending, @wl_scheduled, @works,
- *	     @erroneous, and @erroneous_peb_count fields
+ *	     @erroneous, @erroneous_peb_count, @fm_work_scheduled, @fm_pool,
+ *	     and @fm_wl_pool fields
  * @move_mutex: serializes eraseblock moves
- * @work_sem: synchronizes the WL worker with use tasks
+ * @work_sem: used to wait for all the scheduled works to finish and prevent
+ * new works from being submitted
  * @wl_scheduled: non-zero if the wear-leveling was scheduled
  * @lookuptbl: a table to quickly find a &struct ubi_wl_entry object for any
  *             physical eraseblock
@@ -474,7 +512,7 @@
  * @vid_hdr_offset: starting offset of the volume identifier header (might be
  *                  unaligned)
  * @vid_hdr_aloffset: starting offset of the VID header aligned to
- * @hdrs_min_io_size
+ *                    @hdrs_min_io_size
  * @vid_hdr_shift: contains @vid_hdr_offset - @vid_hdr_aloffset
  * @bad_allowed: whether the MTD device admits of bad physical eraseblocks or
  *               not
@@ -527,13 +565,14 @@
 	struct ubi_fastmap_layout *fm;
 	struct ubi_fm_pool fm_pool;
 	struct ubi_fm_pool fm_wl_pool;
-	struct rw_semaphore fm_sem;
-	struct mutex fm_mutex;
+	struct rw_semaphore fm_eba_sem;
+	struct rw_semaphore fm_protect;
 	void *fm_buf;
 	size_t fm_size;
 #ifndef __UBOOT__
 	struct work_struct fm_work;
 #endif
+	int fm_work_scheduled;
 
 	/* Wear-leveling sub-system's stuff */
 	struct rb_root used;
@@ -716,14 +755,15 @@
  * @torture: if the physical eraseblock has to be tortured
  * @anchor: produce a anchor PEB to by used by fastmap
  *
- * The @func pointer points to the worker function. If the @cancel argument is
- * not zero, the worker has to free the resources and exit immediately. The
- * worker has to return zero in case of success and a negative error code in
+ * The @func pointer points to the worker function. If the @shutdown argument is
+ * not zero, the worker has to free the resources and exit immediately as the
+ * WL sub-system is shutting down.
+ * The worker has to return zero in case of success and a negative error code in
  * case of failure.
  */
 struct ubi_work {
 	struct list_head list;
-	int (*func)(struct ubi_device *ubi, struct ubi_work *wrk, int cancel);
+	int (*func)(struct ubi_device *ubi, struct ubi_work *wrk, int shutdown);
 	/* The below fields are only relevant to erasure works */
 	struct ubi_wl_entry *e;
 	int vol_id;
@@ -738,7 +778,7 @@
 extern const struct file_operations ubi_ctrl_cdev_operations;
 extern const struct file_operations ubi_cdev_operations;
 extern const struct file_operations ubi_vol_cdev_operations;
-extern struct class *ubi_class;
+extern struct class ubi_class;
 extern struct mutex ubi_devices_mutex;
 extern struct blocking_notifier_head ubi_notifiers;
 
@@ -807,6 +847,9 @@
 		      int lnum);
 int ubi_eba_read_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
 		     void *buf, int offset, int len, int check);
+int ubi_eba_read_leb_sg(struct ubi_device *ubi, struct ubi_volume *vol,
+			struct ubi_sgl *sgl, int lnum, int offset, int len,
+			int check);
 int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
 		      const void *buf, int offset, int len);
 int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol,
@@ -877,10 +920,14 @@
 		      int pnum, const struct ubi_vid_hdr *vid_hdr);
 
 /* fastmap.c */
+#ifdef CONFIG_MTD_UBI_FASTMAP
 size_t ubi_calc_fm_size(struct ubi_device *ubi);
 int ubi_update_fastmap(struct ubi_device *ubi);
 int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai,
 		     int fm_anchor);
+#else
+static inline int ubi_update_fastmap(struct ubi_device *ubi) { return 0; }
+#endif
 
 /* block.c */
 #ifdef CONFIG_MTD_UBI_BLOCK
@@ -901,8 +948,44 @@
 }
 #endif
 
+/*
+ * ubi_for_each_free_peb - walk the UBI free RB tree.
+ * @ubi: UBI device description object
+ * @e: a pointer to a ubi_wl_entry to use as cursor
+ * @pos: a pointer to RB-tree entry type to use as a loop counter
+ */
+#define ubi_for_each_free_peb(ubi, e, tmp_rb)	\
+	ubi_rb_for_each_entry((tmp_rb), (e), &(ubi)->free, u.rb)
 
 /*
+ * ubi_for_each_used_peb - walk the UBI used RB tree.
+ * @ubi: UBI device description object
+ * @e: a pointer to a ubi_wl_entry to use as cursor
+ * @pos: a pointer to RB-tree entry type to use as a loop counter
+ */
+#define ubi_for_each_used_peb(ubi, e, tmp_rb)	\
+	ubi_rb_for_each_entry((tmp_rb), (e), &(ubi)->used, u.rb)
+
+/*
+ * ubi_for_each_scub_peb - walk the UBI scub RB tree.
+ * @ubi: UBI device description object
+ * @e: a pointer to a ubi_wl_entry to use as cursor
+ * @pos: a pointer to RB-tree entry type to use as a loop counter
+ */
+#define ubi_for_each_scrub_peb(ubi, e, tmp_rb)	\
+	ubi_rb_for_each_entry((tmp_rb), (e), &(ubi)->scrub, u.rb)
+
+/*
+ * ubi_for_each_protected_peb - walk the UBI protection queue.
+ * @ubi: UBI device description object
+ * @i: a integer used as counter
+ * @e: a pointer to a ubi_wl_entry to use as cursor
+ */
+#define ubi_for_each_protected_peb(ubi, i, e)	\
+	for ((i) = 0; (i) < UBI_PROT_QUEUE_LEN; (i)++)	\
+		list_for_each_entry((e), &(ubi->pq[(i)]), u.list)
+
+/*
  * ubi_rb_for_each_entry - walk an RB-tree.
  * @rb: a pointer to type 'struct rb_node' to use as a loop counter
  * @pos: a pointer to RB-tree entry type to use as a loop counter
@@ -1004,7 +1087,7 @@
 {
 	if (!ubi->ro_mode) {
 		ubi->ro_mode = 1;
-		ubi_warn("switch to read-only mode");
+		ubi_warn(ubi, "switch to read-only mode");
 		dump_stack();
 	}
 }
@@ -1035,4 +1118,7 @@
 		return idx;
 }
 
+#ifdef __UBOOT__
+int do_work(struct ubi_device *ubi);
+#endif
 #endif /* !__UBI_UBI_H__ */
diff --git a/drivers/mtd/ubi/upd.c b/drivers/mtd/ubi/upd.c
index c52c9ce..e0caf8e 100644
--- a/drivers/mtd/ubi/upd.c
+++ b/drivers/mtd/ubi/upd.c
@@ -127,6 +127,10 @@
 	ubi_assert(!vol->updating && !vol->changing_leb);
 	vol->updating = 1;
 
+	vol->upd_buf = vmalloc(ubi->leb_size);
+	if (!vol->upd_buf)
+		return -ENOMEM;
+
 	err = set_update_marker(ubi, vol);
 	if (err)
 		return err;
@@ -146,14 +150,12 @@
 		err = clear_update_marker(ubi, vol, 0);
 		if (err)
 			return err;
+
+		vfree(vol->upd_buf);
 		vol->updating = 0;
 		return 0;
 	}
 
-	vol->upd_buf = vmalloc(ubi->leb_size);
-	if (!vol->upd_buf)
-		return -ENOMEM;
-
 	vol->upd_ebs = div_u64(bytes + vol->usable_leb_size - 1,
 			       vol->usable_leb_size);
 	vol->upd_bytes = bytes;
diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c
index f4392f5..f8ab08f 100644
--- a/drivers/mtd/ubi/vmt.c
+++ b/drivers/mtd/ubi/vmt.c
@@ -114,6 +114,19 @@
 	ubi_put_device(ubi);
 	return ret;
 }
+
+static struct attribute *volume_dev_attrs[] = {
+	&attr_vol_reserved_ebs.attr,
+	&attr_vol_type.attr,
+	&attr_vol_name.attr,
+	&attr_vol_corrupted.attr,
+	&attr_vol_alignment.attr,
+	&attr_vol_usable_eb_size.attr,
+	&attr_vol_data_bytes.attr,
+	&attr_vol_upd_marker.attr,
+	NULL
+};
+ATTRIBUTE_GROUPS(volume_dev);
 #endif
 
 /* Release method for volume devices */
@@ -125,66 +138,6 @@
 	kfree(vol);
 }
 
-#ifndef __UBOOT__
-/**
- * volume_sysfs_init - initialize sysfs for new volume.
- * @ubi: UBI device description object
- * @vol: volume description object
- *
- * This function returns zero in case of success and a negative error code in
- * case of failure.
- *
- * Note, this function does not free allocated resources in case of failure -
- * the caller does it. This is because this would cause release() here and the
- * caller would oops.
- */
-static int volume_sysfs_init(struct ubi_device *ubi, struct ubi_volume *vol)
-{
-	int err;
-
-	err = device_create_file(&vol->dev, &attr_vol_reserved_ebs);
-	if (err)
-		return err;
-	err = device_create_file(&vol->dev, &attr_vol_type);
-	if (err)
-		return err;
-	err = device_create_file(&vol->dev, &attr_vol_name);
-	if (err)
-		return err;
-	err = device_create_file(&vol->dev, &attr_vol_corrupted);
-	if (err)
-		return err;
-	err = device_create_file(&vol->dev, &attr_vol_alignment);
-	if (err)
-		return err;
-	err = device_create_file(&vol->dev, &attr_vol_usable_eb_size);
-	if (err)
-		return err;
-	err = device_create_file(&vol->dev, &attr_vol_data_bytes);
-	if (err)
-		return err;
-	err = device_create_file(&vol->dev, &attr_vol_upd_marker);
-	return err;
-}
-
-/**
- * volume_sysfs_close - close sysfs for a volume.
- * @vol: volume description object
- */
-static void volume_sysfs_close(struct ubi_volume *vol)
-{
-	device_remove_file(&vol->dev, &attr_vol_upd_marker);
-	device_remove_file(&vol->dev, &attr_vol_data_bytes);
-	device_remove_file(&vol->dev, &attr_vol_usable_eb_size);
-	device_remove_file(&vol->dev, &attr_vol_alignment);
-	device_remove_file(&vol->dev, &attr_vol_corrupted);
-	device_remove_file(&vol->dev, &attr_vol_name);
-	device_remove_file(&vol->dev, &attr_vol_type);
-	device_remove_file(&vol->dev, &attr_vol_reserved_ebs);
-	device_unregister(&vol->dev);
-}
-#endif
-
 /**
  * ubi_create_volume - create volume.
  * @ubi: UBI device description object
@@ -221,7 +174,7 @@
 			}
 
 		if (vol_id == UBI_VOL_NUM_AUTO) {
-			ubi_err("out of volume IDs");
+			ubi_err(ubi, "out of volume IDs");
 			err = -ENFILE;
 			goto out_unlock;
 		}
@@ -235,7 +188,7 @@
 	/* Ensure that this volume does not exist */
 	err = -EEXIST;
 	if (ubi->volumes[vol_id]) {
-		ubi_err("volume %d already exists", vol_id);
+		ubi_err(ubi, "volume %d already exists", vol_id);
 		goto out_unlock;
 	}
 
@@ -244,20 +197,22 @@
 		if (ubi->volumes[i] &&
 		    ubi->volumes[i]->name_len == req->name_len &&
 		    !strcmp(ubi->volumes[i]->name, req->name)) {
-			ubi_err("volume \"%s\" exists (ID %d)", req->name, i);
+			ubi_err(ubi, "volume \"%s\" exists (ID %d)",
+				req->name, i);
 			goto out_unlock;
 		}
 
 	/* Calculate how many eraseblocks are requested */
 	vol->usable_leb_size = ubi->leb_size - ubi->leb_size % req->alignment;
-	vol->reserved_pebs += div_u64(req->bytes + vol->usable_leb_size - 1,
-				      vol->usable_leb_size);
+	vol->reserved_pebs = div_u64(req->bytes + vol->usable_leb_size - 1,
+				     vol->usable_leb_size);
 
 	/* Reserve physical eraseblocks */
 	if (vol->reserved_pebs > ubi->avail_pebs) {
-		ubi_err("not enough PEBs, only %d available", ubi->avail_pebs);
+		ubi_err(ubi, "not enough PEBs, only %d available",
+			ubi->avail_pebs);
 		if (ubi->corr_peb_count)
-			ubi_err("%d PEBs are corrupted and not used",
+			ubi_err(ubi, "%d PEBs are corrupted and not used",
 				ubi->corr_peb_count);
 		err = -ENOSPC;
 		goto out_unlock;
@@ -312,26 +267,25 @@
 	dev = MKDEV(MAJOR(ubi->cdev.dev), vol_id + 1);
 	err = cdev_add(&vol->cdev, dev, 1);
 	if (err) {
-		ubi_err("cannot add character device");
+		ubi_err(ubi, "cannot add character device");
 		goto out_mapping;
 	}
 
 	vol->dev.release = vol_release;
 	vol->dev.parent = &ubi->dev;
 	vol->dev.devt = dev;
-	vol->dev.class = ubi_class;
+#ifndef __UBOOT__
+	vol->dev.class = &ubi_class;
+	vol->dev.groups = volume_dev_groups;
+#endif
 
 	dev_set_name(&vol->dev, "%s_%d", ubi->ubi_name, vol->vol_id);
 	err = device_register(&vol->dev);
 	if (err) {
-		ubi_err("cannot register device");
+		ubi_err(ubi, "cannot register device");
 		goto out_cdev;
 	}
 
-	err = volume_sysfs_init(ubi, vol);
-	if (err)
-		goto out_sysfs;
-
 	/* Fill volume table record */
 	memset(&vtbl_rec, 0, sizeof(struct ubi_vtbl_record));
 	vtbl_rec.reserved_pebs = cpu_to_be32(vol->reserved_pebs);
@@ -368,7 +322,7 @@
 	 */
 	do_free = 0;
 	get_device(&vol->dev);
-	volume_sysfs_close(vol);
+	device_unregister(&vol->dev);
 out_cdev:
 	cdev_del(&vol->cdev);
 out_mapping:
@@ -384,7 +338,7 @@
 		kfree(vol);
 	else
 		put_device(&vol->dev);
-	ubi_err("cannot create volume %d, error %d", vol_id, err);
+	ubi_err(ubi, "cannot create volume %d, error %d", vol_id, err);
 	return err;
 }
 
@@ -436,7 +390,7 @@
 	}
 
 	cdev_del(&vol->cdev);
-	volume_sysfs_close(vol);
+	device_unregister(&vol->dev);
 
 	spin_lock(&ubi->volumes_lock);
 	ubi->rsvd_pebs -= reserved_pebs;
@@ -452,7 +406,7 @@
 	return err;
 
 out_err:
-	ubi_err("cannot remove volume %d, error %d", vol_id, err);
+	ubi_err(ubi, "cannot remove volume %d, error %d", vol_id, err);
 	spin_lock(&ubi->volumes_lock);
 	ubi->volumes[vol_id] = vol;
 out_unlock:
@@ -485,7 +439,7 @@
 
 	if (vol->vol_type == UBI_STATIC_VOLUME &&
 	    reserved_pebs < vol->used_ebs) {
-		ubi_err("too small size %d, %d LEBs contain data",
+		ubi_err(ubi, "too small size %d, %d LEBs contain data",
 			reserved_pebs, vol->used_ebs);
 		return -EINVAL;
 	}
@@ -514,10 +468,10 @@
 	if (pebs > 0) {
 		spin_lock(&ubi->volumes_lock);
 		if (pebs > ubi->avail_pebs) {
-			ubi_err("not enough PEBs: requested %d, available %d",
+			ubi_err(ubi, "not enough PEBs: requested %d, available %d",
 				pebs, ubi->avail_pebs);
 			if (ubi->corr_peb_count)
-				ubi_err("%d PEBs are corrupted and not used",
+				ubi_err(ubi, "%d PEBs are corrupted and not used",
 					ubi->corr_peb_count);
 			spin_unlock(&ubi->volumes_lock);
 			err = -ENOSPC;
@@ -641,7 +595,7 @@
 	dev = MKDEV(MAJOR(ubi->cdev.dev), vol->vol_id + 1);
 	err = cdev_add(&vol->cdev, dev, 1);
 	if (err) {
-		ubi_err("cannot add character device for volume %d, error %d",
+		ubi_err(ubi, "cannot add character device for volume %d, error %d",
 			vol_id, err);
 		return err;
 	}
@@ -649,19 +603,15 @@
 	vol->dev.release = vol_release;
 	vol->dev.parent = &ubi->dev;
 	vol->dev.devt = dev;
-	vol->dev.class = ubi_class;
+#ifndef __UBOOT__
+	vol->dev.class = &ubi_class;
+	vol->dev.groups = volume_dev_groups;
+#endif
 	dev_set_name(&vol->dev, "%s_%d", ubi->ubi_name, vol->vol_id);
 	err = device_register(&vol->dev);
 	if (err)
 		goto out_cdev;
 
-	err = volume_sysfs_init(ubi, vol);
-	if (err) {
-		cdev_del(&vol->cdev);
-		volume_sysfs_close(vol);
-		return err;
-	}
-
 	self_check_volumes(ubi);
 	return err;
 
@@ -684,7 +634,7 @@
 
 	ubi->volumes[vol->vol_id] = NULL;
 	cdev_del(&vol->cdev);
-	volume_sysfs_close(vol);
+	device_unregister(&vol->dev);
 }
 
 /**
@@ -708,7 +658,7 @@
 
 	if (!vol) {
 		if (reserved_pebs) {
-			ubi_err("no volume info, but volume exists");
+			ubi_err(ubi, "no volume info, but volume exists");
 			goto fail;
 		}
 		spin_unlock(&ubi->volumes_lock);
@@ -717,90 +667,91 @@
 
 	if (vol->reserved_pebs < 0 || vol->alignment < 0 || vol->data_pad < 0 ||
 	    vol->name_len < 0) {
-		ubi_err("negative values");
+		ubi_err(ubi, "negative values");
 		goto fail;
 	}
 	if (vol->alignment > ubi->leb_size || vol->alignment == 0) {
-		ubi_err("bad alignment");
+		ubi_err(ubi, "bad alignment");
 		goto fail;
 	}
 
 	n = vol->alignment & (ubi->min_io_size - 1);
 	if (vol->alignment != 1 && n) {
-		ubi_err("alignment is not multiple of min I/O unit");
+		ubi_err(ubi, "alignment is not multiple of min I/O unit");
 		goto fail;
 	}
 
 	n = ubi->leb_size % vol->alignment;
 	if (vol->data_pad != n) {
-		ubi_err("bad data_pad, has to be %lld", n);
+		ubi_err(ubi, "bad data_pad, has to be %lld", n);
 		goto fail;
 	}
 
 	if (vol->vol_type != UBI_DYNAMIC_VOLUME &&
 	    vol->vol_type != UBI_STATIC_VOLUME) {
-		ubi_err("bad vol_type");
+		ubi_err(ubi, "bad vol_type");
 		goto fail;
 	}
 
 	if (vol->upd_marker && vol->corrupted) {
-		ubi_err("update marker and corrupted simultaneously");
+		ubi_err(ubi, "update marker and corrupted simultaneously");
 		goto fail;
 	}
 
 	if (vol->reserved_pebs > ubi->good_peb_count) {
-		ubi_err("too large reserved_pebs");
+		ubi_err(ubi, "too large reserved_pebs");
 		goto fail;
 	}
 
 	n = ubi->leb_size - vol->data_pad;
 	if (vol->usable_leb_size != ubi->leb_size - vol->data_pad) {
-		ubi_err("bad usable_leb_size, has to be %lld", n);
+		ubi_err(ubi, "bad usable_leb_size, has to be %lld", n);
 		goto fail;
 	}
 
 	if (vol->name_len > UBI_VOL_NAME_MAX) {
-		ubi_err("too long volume name, max is %d", UBI_VOL_NAME_MAX);
+		ubi_err(ubi, "too long volume name, max is %d",
+			UBI_VOL_NAME_MAX);
 		goto fail;
 	}
 
 	n = strnlen(vol->name, vol->name_len + 1);
 	if (n != vol->name_len) {
-		ubi_err("bad name_len %lld", n);
+		ubi_err(ubi, "bad name_len %lld", n);
 		goto fail;
 	}
 
 	n = (long long)vol->used_ebs * vol->usable_leb_size;
 	if (vol->vol_type == UBI_DYNAMIC_VOLUME) {
 		if (vol->corrupted) {
-			ubi_err("corrupted dynamic volume");
+			ubi_err(ubi, "corrupted dynamic volume");
 			goto fail;
 		}
 		if (vol->used_ebs != vol->reserved_pebs) {
-			ubi_err("bad used_ebs");
+			ubi_err(ubi, "bad used_ebs");
 			goto fail;
 		}
 		if (vol->last_eb_bytes != vol->usable_leb_size) {
-			ubi_err("bad last_eb_bytes");
+			ubi_err(ubi, "bad last_eb_bytes");
 			goto fail;
 		}
 		if (vol->used_bytes != n) {
-			ubi_err("bad used_bytes");
+			ubi_err(ubi, "bad used_bytes");
 			goto fail;
 		}
 	} else {
 		if (vol->used_ebs < 0 || vol->used_ebs > vol->reserved_pebs) {
-			ubi_err("bad used_ebs");
+			ubi_err(ubi, "bad used_ebs");
 			goto fail;
 		}
 		if (vol->last_eb_bytes < 0 ||
 		    vol->last_eb_bytes > vol->usable_leb_size) {
-			ubi_err("bad last_eb_bytes");
+			ubi_err(ubi, "bad last_eb_bytes");
 			goto fail;
 		}
 		if (vol->used_bytes < 0 || vol->used_bytes > n ||
 		    vol->used_bytes < n - vol->usable_leb_size) {
-			ubi_err("bad used_bytes");
+			ubi_err(ubi, "bad used_bytes");
 			goto fail;
 		}
 	}
@@ -818,7 +769,7 @@
 	if (alignment != vol->alignment || data_pad != vol->data_pad ||
 	    upd_marker != vol->upd_marker || vol_type != vol->vol_type ||
 	    name_len != vol->name_len || strncmp(name, vol->name, name_len)) {
-		ubi_err("volume info is different");
+		ubi_err(ubi, "volume info is different");
 		goto fail;
 	}
 
@@ -826,7 +777,7 @@
 	return 0;
 
 fail:
-	ubi_err("self-check failed for volume %d", vol_id);
+	ubi_err(ubi, "self-check failed for volume %d", vol_id);
 	if (vol)
 		ubi_dump_vol_info(vol);
 	ubi_dump_vtbl_record(&ubi->vtbl[vol_id], vol_id);
diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c
index ae8ea38..993716f 100644
--- a/drivers/mtd/ubi/vtbl.c
+++ b/drivers/mtd/ubi/vtbl.c
@@ -18,9 +18,12 @@
  * eraseblock stores one volume table copy, i.e. LEB 0 and LEB 1 duplicate each
  * other. This redundancy guarantees robustness to unclean reboots. The volume
  * table is basically an array of volume table records. Each record contains
- * full information about the volume and protected by a CRC checksum.
+ * full information about the volume and protected by a CRC checksum. Note,
+ * nowadays we use the atomic LEB change operation when updating the volume
+ * table, so we do not really need 2 LEBs anymore, but we preserve the older
+ * design for the backward compatibility reasons.
  *
- * The volume table is changed, it is first changed in RAM. Then LEB 0 is
+ * When the volume table is changed, it is first changed in RAM. Then LEB 0 is
  * erased, and the updated volume table is written back to LEB 0. Then same for
  * LEB 1. This scheme guarantees recoverability from unclean reboots.
  *
@@ -61,6 +64,26 @@
 static struct ubi_vtbl_record empty_vtbl_record;
 
 /**
+ * ubi_update_layout_vol - helper for updatting layout volumes on flash
+ * @ubi: UBI device description object
+ */
+static int ubi_update_layout_vol(struct ubi_device *ubi)
+{
+	struct ubi_volume *layout_vol;
+	int i, err;
+
+	layout_vol = ubi->volumes[vol_id2idx(ubi, UBI_LAYOUT_VOLUME_ID)];
+	for (i = 0; i < UBI_LAYOUT_VOLUME_EBS; i++) {
+		err = ubi_eba_atomic_leb_change(ubi, layout_vol, i, ubi->vtbl,
+						ubi->vtbl_size);
+		if (err)
+			return err;
+	}
+
+	return 0;
+}
+
+/**
  * ubi_change_vtbl_record - change volume table record.
  * @ubi: UBI device description object
  * @idx: table index to change
@@ -74,12 +97,10 @@
 int ubi_change_vtbl_record(struct ubi_device *ubi, int idx,
 			   struct ubi_vtbl_record *vtbl_rec)
 {
-	int i, err;
+	int err;
 	uint32_t crc;
-	struct ubi_volume *layout_vol;
 
 	ubi_assert(idx >= 0 && idx < ubi->vtbl_slots);
-	layout_vol = ubi->volumes[vol_id2idx(ubi, UBI_LAYOUT_VOLUME_ID)];
 
 	if (!vtbl_rec)
 		vtbl_rec = &empty_vtbl_record;
@@ -89,19 +110,10 @@
 	}
 
 	memcpy(&ubi->vtbl[idx], vtbl_rec, sizeof(struct ubi_vtbl_record));
-	for (i = 0; i < UBI_LAYOUT_VOLUME_EBS; i++) {
-		err = ubi_eba_unmap_leb(ubi, layout_vol, i);
-		if (err)
-			return err;
-
-		err = ubi_eba_write_leb(ubi, layout_vol, i, ubi->vtbl, 0,
-					ubi->vtbl_size);
-		if (err)
-			return err;
-	}
+	err = ubi_update_layout_vol(ubi);
 
 	self_vtbl_check(ubi);
-	return 0;
+	return err ? err : 0;
 }
 
 /**
@@ -116,9 +128,7 @@
 int ubi_vtbl_rename_volumes(struct ubi_device *ubi,
 			    struct list_head *rename_list)
 {
-	int i, err;
 	struct ubi_rename_entry *re;
-	struct ubi_volume *layout_vol;
 
 	list_for_each_entry(re, rename_list, list) {
 		uint32_t crc;
@@ -140,19 +150,7 @@
 		vtbl_rec->crc = cpu_to_be32(crc);
 	}
 
-	layout_vol = ubi->volumes[vol_id2idx(ubi, UBI_LAYOUT_VOLUME_ID)];
-	for (i = 0; i < UBI_LAYOUT_VOLUME_EBS; i++) {
-		err = ubi_eba_unmap_leb(ubi, layout_vol, i);
-		if (err)
-			return err;
-
-		err = ubi_eba_write_leb(ubi, layout_vol, i, ubi->vtbl, 0,
-					ubi->vtbl_size);
-		if (err)
-			return err;
-	}
-
-	return 0;
+	return ubi_update_layout_vol(ubi);
 }
 
 /**
@@ -184,7 +182,7 @@
 
 		crc = crc32(UBI_CRC32_INIT, &vtbl[i], UBI_VTBL_RECORD_SIZE_CRC);
 		if (be32_to_cpu(vtbl[i].crc) != crc) {
-			ubi_err("bad CRC at record %u: %#08x, not %#08x",
+			ubi_err(ubi, "bad CRC at record %u: %#08x, not %#08x",
 				 i, crc, be32_to_cpu(vtbl[i].crc));
 			ubi_dump_vtbl_record(&vtbl[i], i);
 			return 1;
@@ -218,7 +216,7 @@
 
 		n = ubi->leb_size % alignment;
 		if (data_pad != n) {
-			ubi_err("bad data_pad, has to be %d", n);
+			ubi_err(ubi, "bad data_pad, has to be %d", n);
 			err = 6;
 			goto bad;
 		}
@@ -234,7 +232,7 @@
 		}
 
 		if (reserved_pebs > ubi->good_peb_count) {
-			ubi_err("too large reserved_pebs %d, good PEBs %d",
+			ubi_err(ubi, "too large reserved_pebs %d, good PEBs %d",
 				reserved_pebs, ubi->good_peb_count);
 			err = 9;
 			goto bad;
@@ -268,7 +266,7 @@
 #else
 			    !strncmp((char *)vtbl[i].name, vtbl[n].name, len1)) {
 #endif
-				ubi_err("volumes %d and %d have the same name \"%s\"",
+				ubi_err(ubi, "volumes %d and %d have the same name \"%s\"",
 					i, n, vtbl[i].name);
 				ubi_dump_vtbl_record(&vtbl[i], i);
 				ubi_dump_vtbl_record(&vtbl[n], n);
@@ -280,7 +278,7 @@
 	return 0;
 
 bad:
-	ubi_err("volume table check failed: record %d, error %d", i, err);
+	ubi_err(ubi, "volume table check failed: record %d, error %d", i, err);
 	ubi_dump_vtbl_record(&vtbl[i], i);
 	return -EINVAL;
 }
@@ -444,11 +442,11 @@
 			leb_corrupted[1] = memcmp(leb[0], leb[1],
 						  ubi->vtbl_size);
 		if (leb_corrupted[1]) {
-			ubi_warn("volume table copy #2 is corrupted");
+			ubi_warn(ubi, "volume table copy #2 is corrupted");
 			err = create_vtbl(ubi, ai, 1, leb[0]);
 			if (err)
 				goto out_free;
-			ubi_msg("volume table was restored");
+			ubi_msg(ubi, "volume table was restored");
 		}
 
 		/* Both LEB 1 and LEB 2 are OK and consistent */
@@ -463,15 +461,15 @@
 		}
 		if (leb_corrupted[1]) {
 			/* Both LEB 0 and LEB 1 are corrupted */
-			ubi_err("both volume tables are corrupted");
+			ubi_err(ubi, "both volume tables are corrupted");
 			goto out_free;
 		}
 
-		ubi_warn("volume table copy #1 is corrupted");
+		ubi_warn(ubi, "volume table copy #1 is corrupted");
 		err = create_vtbl(ubi, ai, 0, leb[1]);
 		if (err)
 			goto out_free;
-		ubi_msg("volume table was restored");
+		ubi_msg(ubi, "volume table was restored");
 
 		vfree(leb[0]);
 		return leb[1];
@@ -560,7 +558,7 @@
 		if (vtbl[i].flags & UBI_VTBL_AUTORESIZE_FLG) {
 			/* Auto re-size flag may be set only for one volume */
 			if (ubi->autoresize_vol_id != -1) {
-				ubi_err("more than one auto-resize volume (%d and %d)",
+				ubi_err(ubi, "more than one auto-resize volume (%d and %d)",
 					ubi->autoresize_vol_id, i);
 				kfree(vol);
 				return -EINVAL;
@@ -589,7 +587,7 @@
 
 		/* Static volumes only */
 		av = ubi_find_av(ai, i);
-		if (!av) {
+		if (!av || !av->leb_count) {
 			/*
 			 * No eraseblocks belonging to this volume found. We
 			 * don't actually know whether this static volume is
@@ -606,7 +604,7 @@
 			 * We found a static volume which misses several
 			 * eraseblocks. Treat it as corrupted.
 			 */
-			ubi_warn("static volume %d misses %d LEBs - corrupted",
+			ubi_warn(ubi, "static volume %d misses %d LEBs - corrupted",
 				 av->vol_id, av->used_ebs - av->leb_count);
 			vol->corrupted = 1;
 			continue;
@@ -644,10 +642,10 @@
 	vol->ubi = ubi;
 
 	if (reserved_pebs > ubi->avail_pebs) {
-		ubi_err("not enough PEBs, required %d, available %d",
+		ubi_err(ubi, "not enough PEBs, required %d, available %d",
 			reserved_pebs, ubi->avail_pebs);
 		if (ubi->corr_peb_count)
-			ubi_err("%d PEBs are corrupted and not used",
+			ubi_err(ubi, "%d PEBs are corrupted and not used",
 				ubi->corr_peb_count);
 	}
 	ubi->rsvd_pebs += reserved_pebs;
@@ -692,7 +690,7 @@
 	return 0;
 
 bad:
-	ubi_err("bad attaching information, error %d", err);
+	ubi_err(vol->ubi, "bad attaching information, error %d", err);
 	ubi_dump_av(av);
 	ubi_dump_vol_info(vol);
 	return -EINVAL;
@@ -716,14 +714,15 @@
 	struct ubi_volume *vol;
 
 	if (ai->vols_found > UBI_INT_VOL_COUNT + ubi->vtbl_slots) {
-		ubi_err("found %d volumes while attaching, maximum is %d + %d",
+		ubi_err(ubi, "found %d volumes while attaching, maximum is %d + %d",
 			ai->vols_found, UBI_INT_VOL_COUNT, ubi->vtbl_slots);
 		return -EINVAL;
 	}
 
 	if (ai->highest_vol_id >= ubi->vtbl_slots + UBI_INT_VOL_COUNT &&
 	    ai->highest_vol_id < UBI_INTERNAL_VOL_START) {
-		ubi_err("too large volume ID %d found", ai->highest_vol_id);
+		ubi_err(ubi, "too large volume ID %d found",
+			ai->highest_vol_id);
 		return -EINVAL;
 	}
 
@@ -751,7 +750,7 @@
 			 * reboot while the volume was being removed. Discard
 			 * these eraseblocks.
 			 */
-			ubi_msg("finish volume %d removal", av->vol_id);
+			ubi_msg(ubi, "finish volume %d removal", av->vol_id);
 			ubi_remove_av(ai, av);
 		} else if (av) {
 			err = check_av(vol, av);
@@ -805,13 +804,13 @@
 			if (IS_ERR(ubi->vtbl))
 				return PTR_ERR(ubi->vtbl);
 		} else {
-			ubi_err("the layout volume was not found");
+			ubi_err(ubi, "the layout volume was not found");
 			return -EINVAL;
 		}
 	} else {
 		if (av->leb_count > UBI_LAYOUT_VOLUME_EBS) {
 			/* This must not happen with proper UBI images */
-			ubi_err("too many LEBs (%d) in layout volume",
+			ubi_err(ubi, "too many LEBs (%d) in layout volume",
 				av->leb_count);
 			return -EINVAL;
 		}
@@ -860,7 +859,7 @@
 		return;
 
 	if (vtbl_check(ubi, ubi->vtbl)) {
-		ubi_err("self-check failed");
+		ubi_err(ubi, "self-check failed");
 		BUG();
 	}
 }
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index 6886f89..507b091 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -96,6 +96,7 @@
 #endif
 
 #include "ubi.h"
+#include "wl.h"
 
 /* Number of physical eraseblocks reserved for wear-leveling purposes */
 #define WL_RESERVED_PEBS 1
@@ -133,44 +134,6 @@
 static int self_check_in_pq(const struct ubi_device *ubi,
 			    struct ubi_wl_entry *e);
 
-#ifdef CONFIG_MTD_UBI_FASTMAP
-#ifndef __UBOOT__
-/**
- * update_fastmap_work_fn - calls ubi_update_fastmap from a work queue
- * @wrk: the work description object
- */
-static void update_fastmap_work_fn(struct work_struct *wrk)
-{
-	struct ubi_device *ubi = container_of(wrk, struct ubi_device, fm_work);
-	ubi_update_fastmap(ubi);
-}
-#endif
-
-/**
- *  ubi_ubi_is_fm_block - returns 1 if a PEB is currently used in a fastmap.
- *  @ubi: UBI device description object
- *  @pnum: the to be checked PEB
- */
-static int ubi_is_fm_block(struct ubi_device *ubi, int pnum)
-{
-	int i;
-
-	if (!ubi->fm)
-		return 0;
-
-	for (i = 0; i < ubi->fm->used_blocks; i++)
-		if (ubi->fm->e[i]->pnum == pnum)
-			return 1;
-
-	return 0;
-}
-#else
-static int ubi_is_fm_block(struct ubi_device *ubi, int pnum)
-{
-	return 0;
-}
-#endif
-
 /**
  * wl_tree_add - add a wear-leveling entry to a WL RB-tree.
  * @e: the wear-leveling entry to add
@@ -208,13 +171,31 @@
 }
 
 /**
+ * wl_tree_destroy - destroy a wear-leveling entry.
+ * @ubi: UBI device description object
+ * @e: the wear-leveling entry to add
+ *
+ * This function destroys a wear leveling entry and removes
+ * the reference from the lookup table.
+ */
+static void wl_entry_destroy(struct ubi_device *ubi, struct ubi_wl_entry *e)
+{
+	ubi->lookuptbl[e->pnum] = NULL;
+	kmem_cache_free(ubi_wl_entry_slab, e);
+}
+
+/**
  * do_work - do one pending work.
  * @ubi: UBI device description object
  *
  * This function returns zero in case of success and a negative error code in
  * case of failure.
  */
+#ifndef __UBOOT__
 static int do_work(struct ubi_device *ubi)
+#else
+int do_work(struct ubi_device *ubi)
+#endif
 {
 	int err;
 	struct ubi_work *wrk;
@@ -248,40 +229,13 @@
 	 */
 	err = wrk->func(ubi, wrk, 0);
 	if (err)
-		ubi_err("work failed with error code %d", err);
+		ubi_err(ubi, "work failed with error code %d", err);
 	up_read(&ubi->work_sem);
 
 	return err;
 }
 
 /**
- * produce_free_peb - produce a free physical eraseblock.
- * @ubi: UBI device description object
- *
- * This function tries to make a free PEB by means of synchronous execution of
- * pending works. This may be needed if, for example the background thread is
- * disabled. Returns zero in case of success and a negative error code in case
- * of failure.
- */
-static int produce_free_peb(struct ubi_device *ubi)
-{
-	int err;
-
-	while (!ubi->free.rb_node) {
-		spin_unlock(&ubi->wl_lock);
-
-		dbg_wl("do one work synchronously");
-		err = do_work(ubi);
-
-		spin_lock(&ubi->wl_lock);
-		if (err)
-			return err;
-	}
-
-	return 0;
-}
-
-/**
  * in_wl_tree - check if wear-leveling entry is present in a WL RB-tree.
  * @e: the wear-leveling entry to check
  * @root: the root of the tree
@@ -404,119 +358,32 @@
 	if (last->ec - first->ec < WL_FREE_MAX_DIFF) {
 		e = rb_entry(root->rb_node, struct ubi_wl_entry, u.rb);
 
-#ifdef CONFIG_MTD_UBI_FASTMAP
 		/* If no fastmap has been written and this WL entry can be used
 		 * as anchor PEB, hold it back and return the second best
 		 * WL entry such that fastmap can use the anchor PEB later. */
-		if (e && !ubi->fm_disabled && !ubi->fm &&
-		    e->pnum < UBI_FM_MAX_START)
-			e = rb_entry(rb_next(root->rb_node),
-				     struct ubi_wl_entry, u.rb);
-#endif
+		e = may_reserve_for_fm(ubi, e, root);
 	} else
 		e = find_wl_entry(ubi, root, WL_FREE_MAX_DIFF/2);
 
 	return e;
 }
 
-#ifdef CONFIG_MTD_UBI_FASTMAP
 /**
- * find_anchor_wl_entry - find wear-leveling entry to used as anchor PEB.
- * @root: the RB-tree where to look for
- */
-static struct ubi_wl_entry *find_anchor_wl_entry(struct rb_root *root)
-{
-	struct rb_node *p;
-	struct ubi_wl_entry *e, *victim = NULL;
-	int max_ec = UBI_MAX_ERASECOUNTER;
-
-	ubi_rb_for_each_entry(p, e, root, u.rb) {
-		if (e->pnum < UBI_FM_MAX_START && e->ec < max_ec) {
-			victim = e;
-			max_ec = e->ec;
-		}
-	}
-
-	return victim;
-}
-
-static int anchor_pebs_avalible(struct rb_root *root)
-{
-	struct rb_node *p;
-	struct ubi_wl_entry *e;
-
-	ubi_rb_for_each_entry(p, e, root, u.rb)
-		if (e->pnum < UBI_FM_MAX_START)
-			return 1;
-
-	return 0;
-}
-
-/**
- * ubi_wl_get_fm_peb - find a physical erase block with a given maximal number.
+ * wl_get_wle - get a mean wl entry to be used by ubi_wl_get_peb() or
+ * refill_wl_user_pool().
  * @ubi: UBI device description object
- * @anchor: This PEB will be used as anchor PEB by fastmap
  *
- * The function returns a physical erase block with a given maximal number
- * and removes it from the wl subsystem.
- * Must be called with wl_lock held!
+ * This function returns a a wear leveling entry in case of success and
+ * NULL in case of failure.
  */
-struct ubi_wl_entry *ubi_wl_get_fm_peb(struct ubi_device *ubi, int anchor)
+static struct ubi_wl_entry *wl_get_wle(struct ubi_device *ubi)
 {
-	struct ubi_wl_entry *e = NULL;
-
-	if (!ubi->free.rb_node || (ubi->free_count - ubi->beb_rsvd_pebs < 1))
-		goto out;
-
-	if (anchor)
-		e = find_anchor_wl_entry(&ubi->free);
-	else
-		e = find_mean_wl_entry(ubi, &ubi->free);
-
-	if (!e)
-		goto out;
-
-	self_check_in_wl_tree(ubi, e, &ubi->free);
-
-	/* remove it from the free list,
-	 * the wl subsystem does no longer know this erase block */
-	rb_erase(&e->u.rb, &ubi->free);
-	ubi->free_count--;
-out:
-	return e;
-}
-#endif
-
-/**
- * __wl_get_peb - get a physical eraseblock.
- * @ubi: UBI device description object
- *
- * This function returns a physical eraseblock in case of success and a
- * negative error code in case of failure.
- */
-static int __wl_get_peb(struct ubi_device *ubi)
-{
-	int err;
 	struct ubi_wl_entry *e;
 
-retry:
-	if (!ubi->free.rb_node) {
-		if (ubi->works_count == 0) {
-			ubi_err("no free eraseblocks");
-			ubi_assert(list_empty(&ubi->works));
-			return -ENOSPC;
-		}
-
-		err = produce_free_peb(ubi);
-		if (err < 0)
-			return err;
-		goto retry;
-	}
-
 	e = find_mean_wl_entry(ubi, &ubi->free);
 	if (!e) {
-		ubi_err("no free eraseblocks");
-		return -ENOSPC;
+		ubi_err(ubi, "no free eraseblocks");
+		return NULL;
 	}
 
 	self_check_in_wl_tree(ubi, e, &ubi->free);
@@ -528,178 +395,10 @@
 	rb_erase(&e->u.rb, &ubi->free);
 	ubi->free_count--;
 	dbg_wl("PEB %d EC %d", e->pnum, e->ec);
-#ifndef CONFIG_MTD_UBI_FASTMAP
-	/* We have to enqueue e only if fastmap is disabled,
-	 * is fastmap enabled prot_queue_add() will be called by
-	 * ubi_wl_get_peb() after removing e from the pool. */
-	prot_queue_add(ubi, e);
-#endif
-	return e->pnum;
-}
-
-#ifdef CONFIG_MTD_UBI_FASTMAP
-/**
- * return_unused_pool_pebs - returns unused PEB to the free tree.
- * @ubi: UBI device description object
- * @pool: fastmap pool description object
- */
-static void return_unused_pool_pebs(struct ubi_device *ubi,
-				    struct ubi_fm_pool *pool)
-{
-	int i;
-	struct ubi_wl_entry *e;
-
-	for (i = pool->used; i < pool->size; i++) {
-		e = ubi->lookuptbl[pool->pebs[i]];
-		wl_tree_add(e, &ubi->free);
-		ubi->free_count++;
-	}
-}
-
-/**
- * refill_wl_pool - refills all the fastmap pool used by the
- * WL sub-system.
- * @ubi: UBI device description object
- */
-static void refill_wl_pool(struct ubi_device *ubi)
-{
-	struct ubi_wl_entry *e;
-	struct ubi_fm_pool *pool = &ubi->fm_wl_pool;
-
-	return_unused_pool_pebs(ubi, pool);
-
-	for (pool->size = 0; pool->size < pool->max_size; pool->size++) {
-		if (!ubi->free.rb_node ||
-		   (ubi->free_count - ubi->beb_rsvd_pebs < 5))
-			break;
-
-		e = find_wl_entry(ubi, &ubi->free, WL_FREE_MAX_DIFF);
-		self_check_in_wl_tree(ubi, e, &ubi->free);
-		rb_erase(&e->u.rb, &ubi->free);
-		ubi->free_count--;
-
-		pool->pebs[pool->size] = e->pnum;
-	}
-	pool->used = 0;
-}
-
-/**
- * refill_wl_user_pool - refills all the fastmap pool used by ubi_wl_get_peb.
- * @ubi: UBI device description object
- */
-static void refill_wl_user_pool(struct ubi_device *ubi)
-{
-	struct ubi_fm_pool *pool = &ubi->fm_pool;
-
-	return_unused_pool_pebs(ubi, pool);
-
-	for (pool->size = 0; pool->size < pool->max_size; pool->size++) {
-		pool->pebs[pool->size] = __wl_get_peb(ubi);
-		if (pool->pebs[pool->size] < 0)
-			break;
-	}
-	pool->used = 0;
-}
-
-/**
- * ubi_refill_pools - refills all fastmap PEB pools.
- * @ubi: UBI device description object
- */
-void ubi_refill_pools(struct ubi_device *ubi)
-{
-	spin_lock(&ubi->wl_lock);
-	refill_wl_pool(ubi);
-	refill_wl_user_pool(ubi);
-	spin_unlock(&ubi->wl_lock);
-}
-
-/* ubi_wl_get_peb - works exaclty like __wl_get_peb but keeps track of
- * the fastmap pool.
- */
-int ubi_wl_get_peb(struct ubi_device *ubi)
-{
-	int ret;
-	struct ubi_fm_pool *pool = &ubi->fm_pool;
-	struct ubi_fm_pool *wl_pool = &ubi->fm_wl_pool;
-
-	if (!pool->size || !wl_pool->size || pool->used == pool->size ||
-	    wl_pool->used == wl_pool->size)
-		ubi_update_fastmap(ubi);
-
-	/* we got not a single free PEB */
-	if (!pool->size)
-		ret = -ENOSPC;
-	else {
-		spin_lock(&ubi->wl_lock);
-		ret = pool->pebs[pool->used++];
-		prot_queue_add(ubi, ubi->lookuptbl[ret]);
-		spin_unlock(&ubi->wl_lock);
-	}
-
-	return ret;
-}
-
-/* get_peb_for_wl - returns a PEB to be used internally by the WL sub-system.
- *
- * @ubi: UBI device description object
- */
-static struct ubi_wl_entry *get_peb_for_wl(struct ubi_device *ubi)
-{
-	struct ubi_fm_pool *pool = &ubi->fm_wl_pool;
-	int pnum;
-
-	if (pool->used == pool->size || !pool->size) {
-		/* We cannot update the fastmap here because this
-		 * function is called in atomic context.
-		 * Let's fail here and refill/update it as soon as possible. */
-#ifndef __UBOOT__
-		schedule_work(&ubi->fm_work);
-#else
-		/* In U-Boot we must call this directly */
-	        ubi_update_fastmap(ubi);
-#endif
-		return NULL;
-	} else {
-		pnum = pool->pebs[pool->used++];
-		return ubi->lookuptbl[pnum];
-	}
-}
-#else
-static struct ubi_wl_entry *get_peb_for_wl(struct ubi_device *ubi)
-{
-	struct ubi_wl_entry *e;
-
-	e = find_wl_entry(ubi, &ubi->free, WL_FREE_MAX_DIFF);
-	self_check_in_wl_tree(ubi, e, &ubi->free);
-	ubi->free_count--;
-	ubi_assert(ubi->free_count >= 0);
-	rb_erase(&e->u.rb, &ubi->free);
 
 	return e;
 }
 
-int ubi_wl_get_peb(struct ubi_device *ubi)
-{
-	int peb, err;
-
-	spin_lock(&ubi->wl_lock);
-	peb = __wl_get_peb(ubi);
-	spin_unlock(&ubi->wl_lock);
-
-	if (peb < 0)
-		return peb;
-
-	err = ubi_self_check_all_ff(ubi, peb, ubi->vid_hdr_aloffset,
-				    ubi->peb_size - ubi->vid_hdr_aloffset);
-	if (err) {
-		ubi_err("new PEB %d does not contain all 0xFF bytes", peb);
-		return err;
-	}
-
-	return peb;
-}
-#endif
-
 /**
  * prot_queue_del - remove a physical eraseblock from the protection queue.
  * @ubi: UBI device description object
@@ -760,7 +459,7 @@
 		 * Erase counter overflow. Upgrade UBI and use 64-bit
 		 * erase counters internally.
 		 */
-		ubi_err("erase counter overflow at PEB %d, EC %llu",
+		ubi_err(ubi, "erase counter overflow at PEB %d, EC %llu",
 			e->pnum, ec);
 		err = -EINVAL;
 		goto out_free;
@@ -835,7 +534,7 @@
  * @wrk: the work to schedule
  *
  * This function adds a work defined by @wrk to the tail of the pending works
- * list. Can only be used of ubi->work_sem is already held in read mode!
+ * list. Can only be used if ubi->work_sem is already held in read mode!
  */
 static void __schedule_ubi_work(struct ubi_device *ubi, struct ubi_work *wrk)
 {
@@ -847,11 +546,16 @@
 	if (ubi->thread_enabled && !ubi_dbg_is_bgt_disabled(ubi))
 		wake_up_process(ubi->bgt_thread);
 #else
+	int err;
 	/*
 	 * U-Boot special: We have no bgt_thread in U-Boot!
 	 * So just call do_work() here directly.
 	 */
-	do_work(ubi);
+	err = do_work(ubi);
+	if (err) {
+		ubi_err(ubi, "%s: work failed with error code %d",
+			ubi->bgt_name, err);
+	}
 #endif
 	spin_unlock(&ubi->wl_lock);
 }
@@ -872,18 +576,7 @@
 }
 
 static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
-			int cancel);
-
-#ifdef CONFIG_MTD_UBI_FASTMAP
-/**
- * ubi_is_erase_work - checks whether a work is erase work.
- * @wrk: The work object to be checked
- */
-int ubi_is_erase_work(struct ubi_work *wrk)
-{
-	return wrk->func == erase_worker;
-}
-#endif
+			int shutdown);
 
 /**
  * schedule_erase - schedule an erase work.
@@ -902,7 +595,6 @@
 	struct ubi_work *wl_wrk;
 
 	ubi_assert(e);
-	ubi_assert(!ubi_is_fm_block(ubi, e->pnum));
 
 	dbg_wl("schedule erasure of PEB %d, EC %d, torture %d",
 	       e->pnum, e->ec, torture);
@@ -948,67 +640,23 @@
 
 	return erase_worker(ubi, wl_wrk, 0);
 }
-
-#ifdef CONFIG_MTD_UBI_FASTMAP
-/**
- * ubi_wl_put_fm_peb - returns a PEB used in a fastmap to the wear-leveling
- * sub-system.
- * see: ubi_wl_put_peb()
- *
- * @ubi: UBI device description object
- * @fm_e: physical eraseblock to return
- * @lnum: the last used logical eraseblock number for the PEB
- * @torture: if this physical eraseblock has to be tortured
- */
-int ubi_wl_put_fm_peb(struct ubi_device *ubi, struct ubi_wl_entry *fm_e,
-		      int lnum, int torture)
-{
-	struct ubi_wl_entry *e;
-	int vol_id, pnum = fm_e->pnum;
-
-	dbg_wl("PEB %d", pnum);
-
-	ubi_assert(pnum >= 0);
-	ubi_assert(pnum < ubi->peb_count);
-
-	spin_lock(&ubi->wl_lock);
-	e = ubi->lookuptbl[pnum];
-
-	/* This can happen if we recovered from a fastmap the very
-	 * first time and writing now a new one. In this case the wl system
-	 * has never seen any PEB used by the original fastmap.
-	 */
-	if (!e) {
-		e = fm_e;
-		ubi_assert(e->ec >= 0);
-		ubi->lookuptbl[pnum] = e;
-	} else {
-		e->ec = fm_e->ec;
-		kfree(fm_e);
-	}
-
-	spin_unlock(&ubi->wl_lock);
-
-	vol_id = lnum ? UBI_FM_DATA_VOLUME_ID : UBI_FM_SB_VOLUME_ID;
-	return schedule_erase(ubi, e, vol_id, lnum, torture);
-}
-#endif
 
 /**
  * wear_leveling_worker - wear-leveling worker function.
  * @ubi: UBI device description object
  * @wrk: the work object
- * @cancel: non-zero if the worker has to free memory and exit
+ * @shutdown: non-zero if the worker has to free memory and exit
+ * because the WL-subsystem is shutting down
  *
  * This function copies a more worn out physical eraseblock to a less worn out
  * one. Returns zero in case of success and a negative error code in case of
  * failure.
  */
 static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
-				int cancel)
+				int shutdown)
 {
 	int err, scrubbing = 0, torture = 0, protect = 0, erroneous = 0;
-	int vol_id = -1, uninitialized_var(lnum);
+	int vol_id = -1, lnum = -1;
 #ifdef CONFIG_MTD_UBI_FASTMAP
 	int anchor = wrk->anchor;
 #endif
@@ -1016,7 +664,7 @@
 	struct ubi_vid_hdr *vid_hdr;
 
 	kfree(wrk);
-	if (cancel)
+	if (shutdown)
 		return 0;
 
 	vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
@@ -1144,7 +792,7 @@
 			goto out_not_moved;
 		}
 
-		ubi_err("error %d while reading VID header from PEB %d",
+		ubi_err(ubi, "error %d while reading VID header from PEB %d",
 			err, e1->pnum);
 		goto out_error;
 	}
@@ -1188,7 +836,7 @@
 			 * UBI from trying to move it over and over again.
 			 */
 			if (ubi->erroneous_peb_count > ubi->max_erroneous) {
-				ubi_err("too many erroneous eraseblocks (%d)",
+				ubi_err(ubi, "too many erroneous eraseblocks (%d)",
 					ubi->erroneous_peb_count);
 				goto out_error;
 			}
@@ -1204,7 +852,7 @@
 
 	/* The PEB has been successfully moved */
 	if (scrubbing)
-		ubi_msg("scrubbed PEB %d (LEB %d:%d), data moved to PEB %d",
+		ubi_msg(ubi, "scrubbed PEB %d (LEB %d:%d), data moved to PEB %d",
 			e1->pnum, vol_id, lnum, e2->pnum);
 	ubi_free_vid_hdr(ubi, vid_hdr);
 
@@ -1219,9 +867,8 @@
 
 	err = do_sync_erase(ubi, e1, vol_id, lnum, 0);
 	if (err) {
-		kmem_cache_free(ubi_wl_entry_slab, e1);
 		if (e2)
-			kmem_cache_free(ubi_wl_entry_slab, e2);
+			wl_entry_destroy(ubi, e2);
 		goto out_ro;
 	}
 
@@ -1233,10 +880,8 @@
 		dbg_wl("PEB %d (LEB %d:%d) was put meanwhile, erase",
 		       e2->pnum, vol_id, lnum);
 		err = do_sync_erase(ubi, e2, vol_id, lnum, 0);
-		if (err) {
-			kmem_cache_free(ubi_wl_entry_slab, e2);
+		if (err)
 			goto out_ro;
-		}
 	}
 
 	dbg_wl("done");
@@ -1272,19 +917,18 @@
 
 	ubi_free_vid_hdr(ubi, vid_hdr);
 	err = do_sync_erase(ubi, e2, vol_id, lnum, torture);
-	if (err) {
-		kmem_cache_free(ubi_wl_entry_slab, e2);
+	if (err)
 		goto out_ro;
-	}
+
 	mutex_unlock(&ubi->move_mutex);
 	return 0;
 
 out_error:
 	if (vol_id != -1)
-		ubi_err("error %d while moving PEB %d to PEB %d",
+		ubi_err(ubi, "error %d while moving PEB %d to PEB %d",
 			err, e1->pnum, e2->pnum);
 	else
-		ubi_err("error %d while moving PEB %d (LEB %d:%d) to PEB %d",
+		ubi_err(ubi, "error %d while moving PEB %d (LEB %d:%d) to PEB %d",
 			err, e1->pnum, vol_id, lnum, e2->pnum);
 	spin_lock(&ubi->wl_lock);
 	ubi->move_from = ubi->move_to = NULL;
@@ -1292,8 +936,8 @@
 	spin_unlock(&ubi->wl_lock);
 
 	ubi_free_vid_hdr(ubi, vid_hdr);
-	kmem_cache_free(ubi_wl_entry_slab, e1);
-	kmem_cache_free(ubi_wl_entry_slab, e2);
+	wl_entry_destroy(ubi, e1);
+	wl_entry_destroy(ubi, e2);
 
 out_ro:
 	ubi_ro_mode(ubi);
@@ -1379,43 +1023,12 @@
 	return err;
 }
 
-#ifdef CONFIG_MTD_UBI_FASTMAP
-/**
- * ubi_ensure_anchor_pebs - schedule wear-leveling to produce an anchor PEB.
- * @ubi: UBI device description object
- */
-int ubi_ensure_anchor_pebs(struct ubi_device *ubi)
-{
-	struct ubi_work *wrk;
-
-	spin_lock(&ubi->wl_lock);
-	if (ubi->wl_scheduled) {
-		spin_unlock(&ubi->wl_lock);
-		return 0;
-	}
-	ubi->wl_scheduled = 1;
-	spin_unlock(&ubi->wl_lock);
-
-	wrk = kmalloc(sizeof(struct ubi_work), GFP_NOFS);
-	if (!wrk) {
-		spin_lock(&ubi->wl_lock);
-		ubi->wl_scheduled = 0;
-		spin_unlock(&ubi->wl_lock);
-		return -ENOMEM;
-	}
-
-	wrk->anchor = 1;
-	wrk->func = &wear_leveling_worker;
-	schedule_ubi_work(ubi, wrk);
-	return 0;
-}
-#endif
-
 /**
  * erase_worker - physical eraseblock erase worker function.
  * @ubi: UBI device description object
  * @wl_wrk: the work object
- * @cancel: non-zero if the worker has to free memory and exit
+ * @shutdown: non-zero if the worker has to free memory and exit
+ * because the WL sub-system is shutting down
  *
  * This function erases a physical eraseblock and perform torture testing if
  * needed. It also takes care about marking the physical eraseblock bad if
@@ -1423,7 +1036,7 @@
  * failure.
  */
 static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
-			int cancel)
+			int shutdown)
 {
 	struct ubi_wl_entry *e = wl_wrk->e;
 	int pnum = e->pnum;
@@ -1431,18 +1044,16 @@
 	int lnum = wl_wrk->lnum;
 	int err, available_consumed = 0;
 
-	if (cancel) {
+	if (shutdown) {
 		dbg_wl("cancel erasure of PEB %d EC %d", pnum, e->ec);
 		kfree(wl_wrk);
-		kmem_cache_free(ubi_wl_entry_slab, e);
+		wl_entry_destroy(ubi, e);
 		return 0;
 	}
 
 	dbg_wl("erase PEB %d EC %d LEB %d:%d",
 	       pnum, e->ec, wl_wrk->vol_id, wl_wrk->lnum);
 
-	ubi_assert(!ubi_is_fm_block(ubi, e->pnum));
-
 	err = sync_erase(ubi, e, wl_wrk->torture);
 	if (!err) {
 		/* Fine, we've erased it successfully */
@@ -1464,7 +1075,7 @@
 		return err;
 	}
 
-	ubi_err("failed to erase PEB %d, error %d", pnum, err);
+	ubi_err(ubi, "failed to erase PEB %d, error %d", pnum, err);
 	kfree(wl_wrk);
 
 	if (err == -EINTR || err == -ENOMEM || err == -EAGAIN ||
@@ -1480,7 +1091,7 @@
 		return err;
 	}
 
-	kmem_cache_free(ubi_wl_entry_slab, e);
+	wl_entry_destroy(ubi, e);
 	if (err != -EIO)
 		/*
 		 * If this is not %-EIO, we have no idea what to do. Scheduling
@@ -1492,7 +1103,7 @@
 	/* It is %-EIO, the PEB went bad */
 
 	if (!ubi->bad_allowed) {
-		ubi_err("bad physical eraseblock %d detected", pnum);
+		ubi_err(ubi, "bad physical eraseblock %d detected", pnum);
 		goto out_ro;
 	}
 
@@ -1500,7 +1111,7 @@
 	if (ubi->beb_rsvd_pebs == 0) {
 		if (ubi->avail_pebs == 0) {
 			spin_unlock(&ubi->volumes_lock);
-			ubi_err("no reserved/available physical eraseblocks");
+			ubi_err(ubi, "no reserved/available physical eraseblocks");
 			goto out_ro;
 		}
 		ubi->avail_pebs -= 1;
@@ -1508,7 +1119,7 @@
 	}
 	spin_unlock(&ubi->volumes_lock);
 
-	ubi_msg("mark PEB %d as bad", pnum);
+	ubi_msg(ubi, "mark PEB %d as bad", pnum);
 	err = ubi_io_mark_bad(ubi, pnum);
 	if (err)
 		goto out_ro;
@@ -1529,11 +1140,12 @@
 	ubi->good_peb_count -= 1;
 	ubi_calculate_reserved(ubi);
 	if (available_consumed)
-		ubi_warn("no PEBs in the reserved pool, used an available PEB");
+		ubi_warn(ubi, "no PEBs in the reserved pool, used an available PEB");
 	else if (ubi->beb_rsvd_pebs)
-		ubi_msg("%d PEBs left in the reserve", ubi->beb_rsvd_pebs);
+		ubi_msg(ubi, "%d PEBs left in the reserve",
+			ubi->beb_rsvd_pebs);
 	else
-		ubi_warn("last PEB from the reserve was used");
+		ubi_warn(ubi, "last PEB from the reserve was used");
 	spin_unlock(&ubi->volumes_lock);
 
 	return err;
@@ -1571,6 +1183,8 @@
 	ubi_assert(pnum >= 0);
 	ubi_assert(pnum < ubi->peb_count);
 
+	down_read(&ubi->fm_protect);
+
 retry:
 	spin_lock(&ubi->wl_lock);
 	e = ubi->lookuptbl[pnum];
@@ -1601,6 +1215,7 @@
 		ubi_assert(!ubi->move_to_put);
 		ubi->move_to_put = 1;
 		spin_unlock(&ubi->wl_lock);
+		up_read(&ubi->fm_protect);
 		return 0;
 	} else {
 		if (in_wl_tree(e, &ubi->used)) {
@@ -1619,9 +1234,10 @@
 		} else {
 			err = prot_queue_del(ubi, e->pnum);
 			if (err) {
-				ubi_err("PEB %d not found", pnum);
+				ubi_err(ubi, "PEB %d not found", pnum);
 				ubi_ro_mode(ubi);
 				spin_unlock(&ubi->wl_lock);
+				up_read(&ubi->fm_protect);
 				return err;
 			}
 		}
@@ -1635,6 +1251,7 @@
 		spin_unlock(&ubi->wl_lock);
 	}
 
+	up_read(&ubi->fm_protect);
 	return err;
 }
 
@@ -1652,7 +1269,7 @@
 {
 	struct ubi_wl_entry *e;
 
-	ubi_msg("schedule PEB %d for scrubbing", pnum);
+	ubi_msg(ubi, "schedule PEB %d for scrubbing", pnum);
 
 retry:
 	spin_lock(&ubi->wl_lock);
@@ -1684,7 +1301,7 @@
 
 		err = prot_queue_del(ubi, e->pnum);
 		if (err) {
-			ubi_err("PEB %d not found", pnum);
+			ubi_err(ubi, "PEB %d not found", pnum);
 			ubi_ro_mode(ubi);
 			spin_unlock(&ubi->wl_lock);
 			return err;
@@ -1726,12 +1343,12 @@
 	       vol_id, lnum, ubi->works_count);
 
 	while (found) {
-		struct ubi_work *wrk;
+		struct ubi_work *wrk, *tmp;
 		found = 0;
 
 		down_read(&ubi->work_sem);
 		spin_lock(&ubi->wl_lock);
-		list_for_each_entry(wrk, &ubi->works, list) {
+		list_for_each_entry_safe(wrk, tmp, &ubi->works, list) {
 			if ((vol_id == UBI_ALL || wrk->vol_id == vol_id) &&
 			    (lnum == UBI_ALL || wrk->lnum == lnum)) {
 				list_del(&wrk->list);
@@ -1766,9 +1383,10 @@
 
 /**
  * tree_destroy - destroy an RB-tree.
+ * @ubi: UBI device description object
  * @root: the root of the tree to destroy
  */
-static void tree_destroy(struct rb_root *root)
+static void tree_destroy(struct ubi_device *ubi, struct rb_root *root)
 {
 	struct rb_node *rb;
 	struct ubi_wl_entry *e;
@@ -1790,7 +1408,7 @@
 					rb->rb_right = NULL;
 			}
 
-			kmem_cache_free(ubi_wl_entry_slab, e);
+			wl_entry_destroy(ubi, e);
 		}
 	}
 }
@@ -1804,7 +1422,7 @@
 	int failures = 0;
 	struct ubi_device *ubi = u;
 
-	ubi_msg("background thread \"%s\" started, PID %d",
+	ubi_msg(ubi, "background thread \"%s\" started, PID %d",
 		ubi->bgt_name, task_pid_nr(current));
 
 	set_freezable();
@@ -1829,14 +1447,14 @@
 
 		err = do_work(ubi);
 		if (err) {
-			ubi_err("%s: work failed with error code %d",
+			ubi_err(ubi, "%s: work failed with error code %d",
 				ubi->bgt_name, err);
 			if (failures++ > WL_MAX_FAILURES) {
 				/*
 				 * Too many failures, disable the thread and
 				 * switch to read-only mode.
 				 */
-				ubi_msg("%s: %d consecutive failures",
+				ubi_msg(ubi, "%s: %d consecutive failures",
 					ubi->bgt_name, WL_MAX_FAILURES);
 				ubi_ro_mode(ubi);
 				ubi->thread_enabled = 0;
@@ -1853,11 +1471,18 @@
 }
 
 /**
- * cancel_pending - cancel all pending works.
+ * shutdown_work - shutdown all pending works.
  * @ubi: UBI device description object
  */
-static void cancel_pending(struct ubi_device *ubi)
+static void shutdown_work(struct ubi_device *ubi)
 {
+#ifdef CONFIG_MTD_UBI_FASTMAP
+#ifndef __UBOOT__
+	flush_work(&ubi->fm_work);
+#else
+	/* in U-Boot, we have all work done */
+#endif
+#endif
 	while (!list_empty(&ubi->works)) {
 		struct ubi_work *wrk;
 
@@ -1891,11 +1516,6 @@
 	init_rwsem(&ubi->work_sem);
 	ubi->max_ec = ai->max_ec;
 	INIT_LIST_HEAD(&ubi->works);
-#ifndef __UBOOT__
-#ifdef CONFIG_MTD_UBI_FASTMAP
-	INIT_WORK(&ubi->fm_work, update_fastmap_work_fn);
-#endif
-#endif
 
 	sprintf(ubi->bgt_name, UBI_BGT_NAME_PATTERN, ubi->ubi_num);
 
@@ -1917,10 +1537,9 @@
 
 		e->pnum = aeb->pnum;
 		e->ec = aeb->ec;
-		ubi_assert(!ubi_is_fm_block(ubi, e->pnum));
 		ubi->lookuptbl[e->pnum] = e;
 		if (schedule_erase(ubi, e, aeb->vol_id, aeb->lnum, 0)) {
-			kmem_cache_free(ubi_wl_entry_slab, e);
+			wl_entry_destroy(ubi, e);
 			goto out_free;
 		}
 
@@ -1938,7 +1557,6 @@
 		e->pnum = aeb->pnum;
 		e->ec = aeb->ec;
 		ubi_assert(e->ec >= 0);
-		ubi_assert(!ubi_is_fm_block(ubi, e->pnum));
 
 		wl_tree_add(e, &ubi->free);
 		ubi->free_count++;
@@ -1976,23 +1594,26 @@
 
 	dbg_wl("found %i PEBs", found_pebs);
 
-	if (ubi->fm)
-		ubi_assert(ubi->good_peb_count == \
+	if (ubi->fm) {
+		ubi_assert(ubi->good_peb_count ==
 			   found_pebs + ubi->fm->used_blocks);
+
+		for (i = 0; i < ubi->fm->used_blocks; i++) {
+			e = ubi->fm->e[i];
+			ubi->lookuptbl[e->pnum] = e;
+		}
+	}
 	else
 		ubi_assert(ubi->good_peb_count == found_pebs);
 
 	reserved_pebs = WL_RESERVED_PEBS;
-#ifdef CONFIG_MTD_UBI_FASTMAP
-	/* Reserve enough LEBs to store two fastmaps. */
-	reserved_pebs += (ubi->fm_size / ubi->leb_size) * 2;
-#endif
+	ubi_fastmap_init(ubi, &reserved_pebs);
 
 	if (ubi->avail_pebs < reserved_pebs) {
-		ubi_err("no enough physical eraseblocks (%d, need %d)",
+		ubi_err(ubi, "no enough physical eraseblocks (%d, need %d)",
 			ubi->avail_pebs, reserved_pebs);
 		if (ubi->corr_peb_count)
-			ubi_err("%d PEBs are corrupted and not used",
+			ubi_err(ubi, "%d PEBs are corrupted and not used",
 				ubi->corr_peb_count);
 		goto out_free;
 	}
@@ -2007,10 +1628,10 @@
 	return 0;
 
 out_free:
-	cancel_pending(ubi);
-	tree_destroy(&ubi->used);
-	tree_destroy(&ubi->free);
-	tree_destroy(&ubi->scrub);
+	shutdown_work(ubi);
+	tree_destroy(ubi, &ubi->used);
+	tree_destroy(ubi, &ubi->free);
+	tree_destroy(ubi, &ubi->scrub);
 	kfree(ubi->lookuptbl);
 	return err;
 }
@@ -2027,7 +1648,7 @@
 	for (i = 0; i < UBI_PROT_QUEUE_LEN; ++i) {
 		list_for_each_entry_safe(e, tmp, &ubi->pq[i], u.list) {
 			list_del(&e->u.list);
-			kmem_cache_free(ubi_wl_entry_slab, e);
+			wl_entry_destroy(ubi, e);
 		}
 	}
 }
@@ -2039,12 +1660,13 @@
 void ubi_wl_close(struct ubi_device *ubi)
 {
 	dbg_wl("close the WL sub-system");
-	cancel_pending(ubi);
+	ubi_fastmap_close(ubi);
+	shutdown_work(ubi);
 	protection_queue_destroy(ubi);
-	tree_destroy(&ubi->used);
-	tree_destroy(&ubi->erroneous);
-	tree_destroy(&ubi->free);
-	tree_destroy(&ubi->scrub);
+	tree_destroy(ubi, &ubi->used);
+	tree_destroy(ubi, &ubi->erroneous);
+	tree_destroy(ubi, &ubi->free);
+	tree_destroy(ubi, &ubi->scrub);
 	kfree(ubi->lookuptbl);
 }
 
@@ -2080,8 +1702,8 @@
 
 	read_ec = be64_to_cpu(ec_hdr->ec);
 	if (ec != read_ec && read_ec - ec > 1) {
-		ubi_err("self-check failed for PEB %d", pnum);
-		ubi_err("read EC is %lld, should be %d", read_ec, ec);
+		ubi_err(ubi, "self-check failed for PEB %d", pnum);
+		ubi_err(ubi, "read EC is %lld, should be %d", read_ec, ec);
 		dump_stack();
 		err = 1;
 	} else
@@ -2110,7 +1732,7 @@
 	if (in_wl_tree(e, root))
 		return 0;
 
-	ubi_err("self-check failed for PEB %d, EC %d, RB-tree %p ",
+	ubi_err(ubi, "self-check failed for PEB %d, EC %d, RB-tree %p ",
 		e->pnum, e->ec, root);
 	dump_stack();
 	return -EINVAL;
@@ -2138,8 +1760,99 @@
 			if (p == e)
 				return 0;
 
-	ubi_err("self-check failed for PEB %d, EC %d, Protect queue",
+	ubi_err(ubi, "self-check failed for PEB %d, EC %d, Protect queue",
 		e->pnum, e->ec);
 	dump_stack();
 	return -EINVAL;
 }
+#ifndef CONFIG_MTD_UBI_FASTMAP
+static struct ubi_wl_entry *get_peb_for_wl(struct ubi_device *ubi)
+{
+	struct ubi_wl_entry *e;
+
+	e = find_wl_entry(ubi, &ubi->free, WL_FREE_MAX_DIFF);
+	self_check_in_wl_tree(ubi, e, &ubi->free);
+	ubi->free_count--;
+	ubi_assert(ubi->free_count >= 0);
+	rb_erase(&e->u.rb, &ubi->free);
+
+	return e;
+}
+
+/**
+ * produce_free_peb - produce a free physical eraseblock.
+ * @ubi: UBI device description object
+ *
+ * This function tries to make a free PEB by means of synchronous execution of
+ * pending works. This may be needed if, for example the background thread is
+ * disabled. Returns zero in case of success and a negative error code in case
+ * of failure.
+ */
+static int produce_free_peb(struct ubi_device *ubi)
+{
+	int err;
+
+	while (!ubi->free.rb_node && ubi->works_count) {
+		spin_unlock(&ubi->wl_lock);
+
+		dbg_wl("do one work synchronously");
+		err = do_work(ubi);
+
+		spin_lock(&ubi->wl_lock);
+		if (err)
+			return err;
+	}
+
+	return 0;
+}
+
+/**
+ * ubi_wl_get_peb - get a physical eraseblock.
+ * @ubi: UBI device description object
+ *
+ * This function returns a physical eraseblock in case of success and a
+ * negative error code in case of failure.
+ * Returns with ubi->fm_eba_sem held in read mode!
+ */
+int ubi_wl_get_peb(struct ubi_device *ubi)
+{
+	int err;
+	struct ubi_wl_entry *e;
+
+retry:
+	down_read(&ubi->fm_eba_sem);
+	spin_lock(&ubi->wl_lock);
+	if (!ubi->free.rb_node) {
+		if (ubi->works_count == 0) {
+			ubi_err(ubi, "no free eraseblocks");
+			ubi_assert(list_empty(&ubi->works));
+			spin_unlock(&ubi->wl_lock);
+			return -ENOSPC;
+		}
+
+		err = produce_free_peb(ubi);
+		if (err < 0) {
+			spin_unlock(&ubi->wl_lock);
+			return err;
+		}
+		spin_unlock(&ubi->wl_lock);
+		up_read(&ubi->fm_eba_sem);
+		goto retry;
+
+	}
+	e = wl_get_wle(ubi);
+	prot_queue_add(ubi, e);
+	spin_unlock(&ubi->wl_lock);
+
+	err = ubi_self_check_all_ff(ubi, e->pnum, ubi->vid_hdr_aloffset,
+				    ubi->peb_size - ubi->vid_hdr_aloffset);
+	if (err) {
+		ubi_err(ubi, "new PEB %d does not contain all 0xFF bytes", e->pnum);
+		return err;
+	}
+
+	return e->pnum;
+}
+#else
+#include "fastmap-wl.c"
+#endif
diff --git a/drivers/mtd/ubi/wl.h b/drivers/mtd/ubi/wl.h
new file mode 100644
index 0000000..662dbe3
--- /dev/null
+++ b/drivers/mtd/ubi/wl.h
@@ -0,0 +1,34 @@
+#ifndef UBI_WL_H
+#define UBI_WL_H
+#ifdef CONFIG_MTD_UBI_FASTMAP
+static int anchor_pebs_avalible(struct rb_root *root);
+#ifndef __UBOOT__
+static void update_fastmap_work_fn(struct work_struct *wrk);
+#else
+void update_fastmap_work_fn(struct ubi_device *ubi);
+#endif
+static struct ubi_wl_entry *find_anchor_wl_entry(struct rb_root *root);
+static struct ubi_wl_entry *get_peb_for_wl(struct ubi_device *ubi);
+static void ubi_fastmap_close(struct ubi_device *ubi);
+static inline void ubi_fastmap_init(struct ubi_device *ubi, int *count)
+{
+	/* Reserve enough LEBs to store two fastmaps. */
+	*count += (ubi->fm_size / ubi->leb_size) * 2;
+#ifndef __UBOOT__
+	INIT_WORK(&ubi->fm_work, update_fastmap_work_fn);
+#endif
+}
+static struct ubi_wl_entry *may_reserve_for_fm(struct ubi_device *ubi,
+					       struct ubi_wl_entry *e,
+					       struct rb_root *root);
+#else /* !CONFIG_MTD_UBI_FASTMAP */
+static struct ubi_wl_entry *get_peb_for_wl(struct ubi_device *ubi);
+static inline void ubi_fastmap_close(struct ubi_device *ubi) { }
+static inline void ubi_fastmap_init(struct ubi_device *ubi, int *count) { }
+static struct ubi_wl_entry *may_reserve_for_fm(struct ubi_device *ubi,
+					       struct ubi_wl_entry *e,
+					       struct rb_root *root) {
+	return e;
+}
+#endif /* CONFIG_MTD_UBI_FASTMAP */
+#endif /* UBI_WL_H */
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 2f8cf19..7d7a9d0 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -139,6 +139,15 @@
 	  access the SPI NOR flash on platforms embedding this Zynq
 	  SPI IP core.
 
+config ZYNQ_QSPI
+	bool "Zynq QSPI driver"
+	depends on ARCH_ZYNQ
+	help
+	  Enable the Zynq Quad-SPI (QSPI) driver. This driver can be
+	  used to access the SPI NOR flash on platforms embedding this
+	  Zynq QSPI IP core. This IP is used to connect the flash in
+	  4-bit qspi, 8-bit dual stacked and shared 4-bit dual parallel.
+
 endif # if DM_SPI
 
 config FSL_ESPI
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index de241be..637fea8 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -49,3 +49,4 @@
 obj-$(CONFIG_TI_QSPI) += ti_qspi.o
 obj-$(CONFIG_XILINX_SPI) += xilinx_spi.o
 obj-$(CONFIG_ZYNQ_SPI) += zynq_spi.o
+obj-$(CONFIG_ZYNQ_QSPI) += zynq_qspi.o
diff --git a/drivers/spi/altera_spi.c b/drivers/spi/altera_spi.c
index ff3512a..e49949b 100644
--- a/drivers/spi/altera_spi.c
+++ b/drivers/spi/altera_spi.c
@@ -11,14 +11,17 @@
 #include <dm.h>
 #include <errno.h>
 #include <malloc.h>
-#include <spi.h>
 #include <fdtdec.h>
+#include <spi.h>
 #include <asm/io.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
+#define ALTERA_SPI_STATUS_RRDY_MSK	BIT(7)
+#define ALTERA_SPI_CONTROL_SSO_MSK	BIT(10)
+
 #ifndef CONFIG_ALTERA_SPI_IDLE_VAL
-#define CONFIG_ALTERA_SPI_IDLE_VAL 0xff
+#define CONFIG_ALTERA_SPI_IDLE_VAL	0xff
 #endif
 
 struct altera_spi_regs {
@@ -38,9 +41,6 @@
 	struct altera_spi_regs *regs;
 };
 
-#define ALTERA_SPI_STATUS_RRDY_MSK	(1 << 7)
-#define ALTERA_SPI_CONTROL_SSO_MSK	(1 << 10)
-
 static void spi_cs_activate(struct udevice *dev, uint cs)
 {
 	struct udevice *bus = dev->parent;
diff --git a/drivers/spi/atmel_spi.h b/drivers/spi/atmel_spi.h
index 1538a23..76b8556 100644
--- a/drivers/spi/atmel_spi.h
+++ b/drivers/spi/atmel_spi.h
@@ -15,19 +15,19 @@
 #define ATMEL_SPI_VERSION		0x00fc
 
 /* Bits in CR */
-#define ATMEL_SPI_CR_SPIEN		(1 << 0)
-#define ATMEL_SPI_CR_SPIDIS		(1 << 1)
-#define ATMEL_SPI_CR_SWRST		(1 << 7)
-#define ATMEL_SPI_CR_LASTXFER		(1 << 24)
+#define ATMEL_SPI_CR_SPIEN		BIT(0)
+#define ATMEL_SPI_CR_SPIDIS		BIT(1)
+#define ATMEL_SPI_CR_SWRST		BIT(7)
+#define ATMEL_SPI_CR_LASTXFER		BIT(24)
 
 /* Bits in MR */
-#define ATMEL_SPI_MR_MSTR		(1 << 0)
-#define ATMEL_SPI_MR_PS			(1 << 1)
-#define ATMEL_SPI_MR_PCSDEC		(1 << 2)
-#define ATMEL_SPI_MR_FDIV		(1 << 3)
-#define ATMEL_SPI_MR_MODFDIS		(1 << 4)
-#define ATMEL_SPI_MR_WDRBT		(1 << 5)
-#define ATMEL_SPI_MR_LLB		(1 << 7)
+#define ATMEL_SPI_MR_MSTR		BIT(0)
+#define ATMEL_SPI_MR_PS			BIT(1)
+#define ATMEL_SPI_MR_PCSDEC		BIT(2)
+#define ATMEL_SPI_MR_FDIV		BIT(3)
+#define ATMEL_SPI_MR_MODFDIS		BIT(4)
+#define ATMEL_SPI_MR_WDRBT		BIT(5)
+#define ATMEL_SPI_MR_LLB		BIT(7)
 #define ATMEL_SPI_MR_PCS(x)		(((x) & 15) << 16)
 #define ATMEL_SPI_MR_DLYBCS(x)		((x) << 24)
 
@@ -38,28 +38,28 @@
 /* Bits in TDR */
 #define ATMEL_SPI_TDR_TD(x)		(x)
 #define ATMEL_SPI_TDR_PCS(x)		((x) << 16)
-#define ATMEL_SPI_TDR_LASTXFER		(1 << 24)
+#define ATMEL_SPI_TDR_LASTXFER		BIT(24)
 
 /* Bits in SR/IER/IDR/IMR */
-#define ATMEL_SPI_SR_RDRF		(1 << 0)
-#define ATMEL_SPI_SR_TDRE		(1 << 1)
-#define ATMEL_SPI_SR_MODF		(1 << 2)
-#define ATMEL_SPI_SR_OVRES		(1 << 3)
-#define ATMEL_SPI_SR_ENDRX		(1 << 4)
-#define ATMEL_SPI_SR_ENDTX		(1 << 5)
-#define ATMEL_SPI_SR_RXBUFF		(1 << 6)
-#define ATMEL_SPI_SR_TXBUFE		(1 << 7)
-#define ATMEL_SPI_SR_NSSR		(1 << 8)
-#define ATMEL_SPI_SR_TXEMPTY		(1 << 9)
-#define ATMEL_SPI_SR_SPIENS		(1 << 16)
+#define ATMEL_SPI_SR_RDRF		BIT(0)
+#define ATMEL_SPI_SR_TDRE		BIT(1)
+#define ATMEL_SPI_SR_MODF		BIT(2)
+#define ATMEL_SPI_SR_OVRES		BIT(3)
+#define ATMEL_SPI_SR_ENDRX		BIT(4)
+#define ATMEL_SPI_SR_ENDTX		BIT(5)
+#define ATMEL_SPI_SR_RXBUFF		BIT(6)
+#define ATMEL_SPI_SR_TXBUFE		BIT(7)
+#define ATMEL_SPI_SR_NSSR		BIT(8)
+#define ATMEL_SPI_SR_TXEMPTY		BIT(9)
+#define ATMEL_SPI_SR_SPIENS		BIT(16)
 
 /* Bits in CSRx */
-#define ATMEL_SPI_CSRx_CPOL		(1 << 0)
-#define ATMEL_SPI_CSRx_NCPHA		(1 << 1)
-#define ATMEL_SPI_CSRx_CSAAT		(1 << 3)
+#define ATMEL_SPI_CSRx_CPOL		BIT(0)
+#define ATMEL_SPI_CSRx_NCPHA		BIT(1)
+#define ATMEL_SPI_CSRx_CSAAT		BIT(3)
 #define ATMEL_SPI_CSRx_BITS(x)		((x) << 4)
 #define ATMEL_SPI_CSRx_SCBR(x)		((x) << 8)
-#define ATMEL_SPI_CSRx_SCBR_MAX		0xff
+#define ATMEL_SPI_CSRx_SCBR_MAX		GENMASK(7, 0)
 #define ATMEL_SPI_CSRx_DLYBS(x)		((x) << 16)
 #define ATMEL_SPI_CSRx_DLYBCT(x)	((x) << 24)
 
diff --git a/drivers/spi/bfin_spi6xx.c b/drivers/spi/bfin_spi6xx.c
index eba01d1..8359d76 100644
--- a/drivers/spi/bfin_spi6xx.c
+++ b/drivers/spi/bfin_spi6xx.c
@@ -63,9 +63,9 @@
 		ssel = bfin_read32(&bss->regs->ssel);
 		ssel |= 1 << slave->cs;
 		if (bss->cs_pol)
-			ssel |= (1 << 8) << slave->cs;
+			ssel |= BIT(8) << slave->cs;
 		else
-			ssel &= ~((1 << 8) << slave->cs);
+			ssel &= ~(BIT(8) << slave->cs);
 		bfin_write32(&bss->regs->ssel, ssel);
 	}
 
@@ -83,9 +83,9 @@
 		u32 ssel;
 		ssel = bfin_read32(&bss->regs->ssel);
 		if (bss->cs_pol)
-			ssel &= ~((1 << 8) << slave->cs);
+			ssel &= ~(BIT(8) << slave->cs);
 		else
-			ssel |= (1 << 8) << slave->cs;
+			ssel |= BIT(8) << slave->cs;
 		/* deassert cs */
 		bfin_write32(&bss->regs->ssel, ssel);
 		SSYNC();
diff --git a/drivers/spi/cadence_qspi_apb.c b/drivers/spi/cadence_qspi_apb.c
index d053407..7786dd6 100644
--- a/drivers/spi/cadence_qspi_apb.c
+++ b/drivers/spi/cadence_qspi_apb.c
@@ -58,10 +58,10 @@
 #define	CQSPI_REG_CONFIG			0x00
 #define	CQSPI_REG_CONFIG_CLK_POL_LSB		1
 #define	CQSPI_REG_CONFIG_CLK_PHA_LSB		2
-#define	CQSPI_REG_CONFIG_ENABLE_MASK		(1 << 0)
-#define	CQSPI_REG_CONFIG_DIRECT_MASK		(1 << 7)
-#define	CQSPI_REG_CONFIG_DECODE_MASK		(1 << 9)
-#define	CQSPI_REG_CONFIG_XIP_IMM_MASK		(1 << 18)
+#define	CQSPI_REG_CONFIG_ENABLE_MASK		BIT(0)
+#define	CQSPI_REG_CONFIG_DIRECT_MASK		BIT(7)
+#define	CQSPI_REG_CONFIG_DECODE_MASK		BIT(9)
+#define	CQSPI_REG_CONFIG_XIP_IMM_MASK		BIT(18)
 #define	CQSPI_REG_CONFIG_CHIPSELECT_LSB		10
 #define	CQSPI_REG_CONFIG_BAUD_LSB		19
 #define	CQSPI_REG_CONFIG_IDLE_LSB		31
@@ -122,18 +122,18 @@
 #define	CQSPI_REG_IRQMASK			0x44
 
 #define	CQSPI_REG_INDIRECTRD			0x60
-#define	CQSPI_REG_INDIRECTRD_START_MASK		(1 << 0)
-#define	CQSPI_REG_INDIRECTRD_CANCEL_MASK	(1 << 1)
-#define	CQSPI_REG_INDIRECTRD_INPROGRESS_MASK	(1 << 2)
-#define	CQSPI_REG_INDIRECTRD_DONE_MASK		(1 << 5)
+#define	CQSPI_REG_INDIRECTRD_START_MASK		BIT(0)
+#define	CQSPI_REG_INDIRECTRD_CANCEL_MASK	BIT(1)
+#define	CQSPI_REG_INDIRECTRD_INPROGRESS_MASK	BIT(2)
+#define	CQSPI_REG_INDIRECTRD_DONE_MASK		BIT(5)
 
 #define	CQSPI_REG_INDIRECTRDWATERMARK		0x64
 #define	CQSPI_REG_INDIRECTRDSTARTADDR		0x68
 #define	CQSPI_REG_INDIRECTRDBYTES		0x6C
 
 #define	CQSPI_REG_CMDCTRL			0x90
-#define	CQSPI_REG_CMDCTRL_EXECUTE_MASK		(1 << 0)
-#define	CQSPI_REG_CMDCTRL_INPROGRESS_MASK	(1 << 1)
+#define	CQSPI_REG_CMDCTRL_EXECUTE_MASK		BIT(0)
+#define	CQSPI_REG_CMDCTRL_INPROGRESS_MASK	BIT(1)
 #define	CQSPI_REG_CMDCTRL_DUMMY_LSB		7
 #define	CQSPI_REG_CMDCTRL_WR_BYTES_LSB		12
 #define	CQSPI_REG_CMDCTRL_WR_EN_LSB		15
@@ -149,10 +149,10 @@
 #define	CQSPI_REG_CMDCTRL_OPCODE_MASK		0xFF
 
 #define	CQSPI_REG_INDIRECTWR			0x70
-#define	CQSPI_REG_INDIRECTWR_START_MASK		(1 << 0)
-#define	CQSPI_REG_INDIRECTWR_CANCEL_MASK	(1 << 1)
-#define	CQSPI_REG_INDIRECTWR_INPROGRESS_MASK	(1 << 2)
-#define	CQSPI_REG_INDIRECTWR_DONE_MASK		(1 << 5)
+#define	CQSPI_REG_INDIRECTWR_START_MASK		BIT(0)
+#define	CQSPI_REG_INDIRECTWR_CANCEL_MASK	BIT(1)
+#define	CQSPI_REG_INDIRECTWR_INPROGRESS_MASK	BIT(2)
+#define	CQSPI_REG_INDIRECTWR_DONE_MASK		BIT(5)
 
 #define	CQSPI_REG_INDIRECTWRWATERMARK		0x74
 #define	CQSPI_REG_INDIRECTWRSTARTADDR		0x78
diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c
index 86ee90f..24a6e98 100644
--- a/drivers/spi/designware_spi.c
+++ b/drivers/spi/designware_spi.c
@@ -74,14 +74,14 @@
 #define SPI_CFS_OFFSET			12
 
 /* Bit fields in SR, 7 bits */
-#define SR_MASK				0x7f		/* cover 7 bits */
-#define SR_BUSY				(1 << 0)
-#define SR_TF_NOT_FULL			(1 << 1)
-#define SR_TF_EMPT			(1 << 2)
-#define SR_RF_NOT_EMPT			(1 << 3)
-#define SR_RF_FULL			(1 << 4)
-#define SR_TX_ERR			(1 << 5)
-#define SR_DCOL				(1 << 6)
+#define SR_MASK				GENMASK(6, 0)	/* cover 7 bits */
+#define SR_BUSY				BIT(0)
+#define SR_TF_NOT_FULL			BIT(1)
+#define SR_TF_EMPT			BIT(2)
+#define SR_RF_NOT_EMPT			BIT(3)
+#define SR_RF_FULL			BIT(4)
+#define SR_TX_ERR			BIT(5)
+#define SR_DCOL				BIT(6)
 
 #define RX_TIMEOUT			1000		/* timeout in ms */
 
diff --git a/drivers/spi/fsl_dspi.c b/drivers/spi/fsl_dspi.c
index 887edd8..c8dcb27 100644
--- a/drivers/spi/fsl_dspi.c
+++ b/drivers/spi/fsl_dspi.c
@@ -24,7 +24,7 @@
 DECLARE_GLOBAL_DATA_PTR;
 
 /* fsl_dspi_platdata flags */
-#define DSPI_FLAG_REGMAP_ENDIAN_BIG	(1 << 0)
+#define DSPI_FLAG_REGMAP_ENDIAN_BIG	BIT(0)
 
 /* idle data value */
 #define DSPI_IDLE_VAL			0x0
diff --git a/drivers/spi/fsl_espi.c b/drivers/spi/fsl_espi.c
index 375dc07..b1586d1 100644
--- a/drivers/spi/fsl_espi.c
+++ b/drivers/spi/fsl_espi.c
@@ -32,26 +32,26 @@
 #define ESPI_MAX_CS_NUM		4
 #define ESPI_FIFO_WIDTH_BIT	32
 
-#define ESPI_EV_RNE		(1 << 9)
-#define ESPI_EV_TNF		(1 << 8)
-#define ESPI_EV_DON		(1 << 14)
-#define ESPI_EV_TXE		(1 << 15)
+#define ESPI_EV_RNE		BIT(9)
+#define ESPI_EV_TNF		BIT(8)
+#define ESPI_EV_DON		BIT(14)
+#define ESPI_EV_TXE		BIT(15)
 #define ESPI_EV_RFCNT_SHIFT	24
 #define ESPI_EV_RFCNT_MASK	(0x3f << ESPI_EV_RFCNT_SHIFT)
 
-#define ESPI_MODE_EN		(1 << 31)	/* Enable interface */
+#define ESPI_MODE_EN		BIT(31)	/* Enable interface */
 #define ESPI_MODE_TXTHR(x)	((x) << 8)	/* Tx FIFO threshold */
 #define ESPI_MODE_RXTHR(x)	((x) << 0)	/* Rx FIFO threshold */
 
 #define ESPI_COM_CS(x)		((x) << 30)
 #define ESPI_COM_TRANLEN(x)	((x) << 0)
 
-#define ESPI_CSMODE_CI_INACTIVEHIGH	(1 << 31)
-#define ESPI_CSMODE_CP_BEGIN_EDGCLK	(1 << 30)
-#define ESPI_CSMODE_REV_MSB_FIRST	(1 << 29)
-#define ESPI_CSMODE_DIV16		(1 << 28)
+#define ESPI_CSMODE_CI_INACTIVEHIGH	BIT(31)
+#define ESPI_CSMODE_CP_BEGIN_EDGCLK	BIT(30)
+#define ESPI_CSMODE_REV_MSB_FIRST	BIT(29)
+#define ESPI_CSMODE_DIV16		BIT(28)
 #define ESPI_CSMODE_PM(x)		((x) << 24)
-#define ESPI_CSMODE_POL_ASSERTED_LOW	(1 << 20)
+#define ESPI_CSMODE_POL_ASSERTED_LOW	BIT(20)
 #define ESPI_CSMODE_LEN(x)		((x) << 16)
 #define ESPI_CSMODE_CSBEF(x)		((x) << 12)
 #define ESPI_CSMODE_CSAFT(x)		((x) << 8)
diff --git a/drivers/spi/fsl_qspi.c b/drivers/spi/fsl_qspi.c
index 868df5f..ed39114 100644
--- a/drivers/spi/fsl_qspi.c
+++ b/drivers/spi/fsl_qspi.c
@@ -24,7 +24,7 @@
 #define TX_BUFFER_SIZE		0x40
 #endif
 
-#define OFFSET_BITS_MASK	0x00ffffff
+#define OFFSET_BITS_MASK	GENMASK(24, 0)
 
 #define FLASH_STATUS_WEL	0x02
 
@@ -68,7 +68,7 @@
 #define QSPI_CMD_SE_4B		0xdc    /* Sector erase (usually 64KiB) */
 
 /* fsl_qspi_platdata flags */
-#define QSPI_FLAG_REGMAP_ENDIAN_BIG	(1 << 0)
+#define QSPI_FLAG_REGMAP_ENDIAN_BIG	BIT(0)
 
 /* default SCK frequency, unit: HZ */
 #define FSL_QSPI_DEFAULT_SCK_FREQ	50000000
@@ -383,7 +383,7 @@
 	/* Enable the module again (enable the DDR too) */
 	reg |= QSPI_MCR_DDR_EN_MASK;
 	/* Enable bit 29 for imx6sx */
-	reg |= (1 << 29);
+	reg |= BIT(29);
 
 	qspi_write32(priv->flags, &regs->mcr, reg);
 }
@@ -913,7 +913,7 @@
 #else
 static int fsl_qspi_child_pre_probe(struct udevice *dev)
 {
-	struct spi_slave *slave = dev_get_parentdata(dev);
+	struct spi_slave *slave = dev_get_parent_priv(dev);
 
 	slave->max_write_size = TX_BUFFER_SIZE;
 
diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c
index be4c0a3..f85af9c 100644
--- a/drivers/spi/ich.c
+++ b/drivers/spi/ich.c
@@ -692,13 +692,13 @@
 	 */
 	if (plat->use_sbase) {
 		bios_cntl = ich_readb(priv, priv->bcr);
-		bios_cntl &= ~(1 << 5);	/* clear Enable InSMM_STS (EISS) */
+		bios_cntl &= ~BIT(5);	/* clear Enable InSMM_STS (EISS) */
 		bios_cntl |= 1;		/* Write Protect Disable (WPD) */
 		ich_writeb(priv, bios_cntl, priv->bcr);
 	} else {
 		pci_read_config_byte(plat->dev, 0xdc, &bios_cntl);
 		if (plat->ich_version == 9)
-			bios_cntl &= ~(1 << 5);
+			bios_cntl &= ~BIT(5);
 		pci_write_config_byte(plat->dev, 0xdc, bios_cntl | 0x1);
 	}
 
@@ -740,7 +740,7 @@
 	struct udevice *bus = dev_get_parent(dev);
 	struct ich_spi_platdata *plat = dev_get_platdata(bus);
 	struct ich_spi_priv *priv = dev_get_priv(bus);
-	struct spi_slave *slave = dev_get_parentdata(dev);
+	struct spi_slave *slave = dev_get_parent_priv(dev);
 
 	/*
 	 * Yes this controller can only write a small number of bytes at
diff --git a/drivers/spi/mpc8xxx_spi.c b/drivers/spi/mpc8xxx_spi.c
index 0d59c36..00cbcbf 100644
--- a/drivers/spi/mpc8xxx_spi.c
+++ b/drivers/spi/mpc8xxx_spi.c
@@ -55,7 +55,7 @@
 	 * some registers
 	 */
 	spi->mode = SPI_MODE_REV | SPI_MODE_MS | SPI_MODE_EN;
-	spi->mode = (spi->mode & 0xfff0ffff) | (1 << 16); /* Use SYSCLK / 8
+	spi->mode = (spi->mode & 0xfff0ffff) | BIT(16); /* Use SYSCLK / 8
 							     (16.67MHz typ.) */
 	spi->event = 0xffffffff;	/* Clear all SPI events */
 	spi->mask = 0x00000000;	/* Mask  all SPI interrupts */
diff --git a/drivers/spi/omap3_spi.h b/drivers/spi/omap3_spi.h
index 4af22c1..6a07c6d 100644
--- a/drivers/spi/omap3_spi.h
+++ b/drivers/spi/omap3_spi.h
@@ -52,40 +52,40 @@
 
 /* per-register bitmasks */
 #define OMAP3_MCSPI_SYSCONFIG_SMARTIDLE (2 << 3)
-#define OMAP3_MCSPI_SYSCONFIG_ENAWAKEUP (1 << 2)
-#define OMAP3_MCSPI_SYSCONFIG_AUTOIDLE	(1 << 0)
-#define OMAP3_MCSPI_SYSCONFIG_SOFTRESET (1 << 1)
+#define OMAP3_MCSPI_SYSCONFIG_ENAWAKEUP BIT(2)
+#define OMAP3_MCSPI_SYSCONFIG_AUTOIDLE	BIT(0)
+#define OMAP3_MCSPI_SYSCONFIG_SOFTRESET BIT(1)
 
-#define OMAP3_MCSPI_SYSSTATUS_RESETDONE (1 << 0)
+#define OMAP3_MCSPI_SYSSTATUS_RESETDONE BIT(0)
 
-#define OMAP3_MCSPI_MODULCTRL_SINGLE	(1 << 0)
-#define OMAP3_MCSPI_MODULCTRL_MS	(1 << 2)
-#define OMAP3_MCSPI_MODULCTRL_STEST	(1 << 3)
+#define OMAP3_MCSPI_MODULCTRL_SINGLE	BIT(0)
+#define OMAP3_MCSPI_MODULCTRL_MS	BIT(2)
+#define OMAP3_MCSPI_MODULCTRL_STEST	BIT(3)
 
-#define OMAP3_MCSPI_CHCONF_PHA		(1 << 0)
-#define OMAP3_MCSPI_CHCONF_POL		(1 << 1)
-#define OMAP3_MCSPI_CHCONF_CLKD_MASK	(0x0f << 2)
-#define OMAP3_MCSPI_CHCONF_EPOL		(1 << 6)
-#define OMAP3_MCSPI_CHCONF_WL_MASK	(0x1f << 7)
-#define OMAP3_MCSPI_CHCONF_TRM_RX_ONLY	(0x01 << 12)
-#define OMAP3_MCSPI_CHCONF_TRM_TX_ONLY	(0x02 << 12)
-#define OMAP3_MCSPI_CHCONF_TRM_MASK	(0x03 << 12)
-#define OMAP3_MCSPI_CHCONF_DMAW		(1 << 14)
-#define OMAP3_MCSPI_CHCONF_DMAR		(1 << 15)
-#define OMAP3_MCSPI_CHCONF_DPE0		(1 << 16)
-#define OMAP3_MCSPI_CHCONF_DPE1		(1 << 17)
-#define OMAP3_MCSPI_CHCONF_IS		(1 << 18)
-#define OMAP3_MCSPI_CHCONF_TURBO	(1 << 19)
-#define OMAP3_MCSPI_CHCONF_FORCE	(1 << 20)
+#define OMAP3_MCSPI_CHCONF_PHA		BIT(0)
+#define OMAP3_MCSPI_CHCONF_POL		BIT(1)
+#define OMAP3_MCSPI_CHCONF_CLKD_MASK	GENMASK(5, 2)
+#define OMAP3_MCSPI_CHCONF_EPOL		BIT(6)
+#define OMAP3_MCSPI_CHCONF_WL_MASK	GENMASK(11, 7)
+#define OMAP3_MCSPI_CHCONF_TRM_RX_ONLY	BIT(12)
+#define OMAP3_MCSPI_CHCONF_TRM_TX_ONLY	BIT(13)
+#define OMAP3_MCSPI_CHCONF_TRM_MASK	GENMASK(13, 12)
+#define OMAP3_MCSPI_CHCONF_DMAW		BIT(14)
+#define OMAP3_MCSPI_CHCONF_DMAR		BIT(15)
+#define OMAP3_MCSPI_CHCONF_DPE0		BIT(16)
+#define OMAP3_MCSPI_CHCONF_DPE1		BIT(17)
+#define OMAP3_MCSPI_CHCONF_IS		BIT(18)
+#define OMAP3_MCSPI_CHCONF_TURBO	BIT(19)
+#define OMAP3_MCSPI_CHCONF_FORCE	BIT(20)
 
-#define OMAP3_MCSPI_CHSTAT_RXS		(1 << 0)
-#define OMAP3_MCSPI_CHSTAT_TXS		(1 << 1)
-#define OMAP3_MCSPI_CHSTAT_EOT		(1 << 2)
+#define OMAP3_MCSPI_CHSTAT_RXS		BIT(0)
+#define OMAP3_MCSPI_CHSTAT_TXS		BIT(1)
+#define OMAP3_MCSPI_CHSTAT_EOT		BIT(2)
 
-#define OMAP3_MCSPI_CHCTRL_EN		(1 << 0)
+#define OMAP3_MCSPI_CHCTRL_EN		BIT(0)
 #define OMAP3_MCSPI_CHCTRL_DIS		(0 << 0)
 
-#define OMAP3_MCSPI_WAKEUPENABLE_WKEN	(1 << 0)
+#define OMAP3_MCSPI_WAKEUPENABLE_WKEN	BIT(0)
 
 struct omap3_spi_slave {
 	struct spi_slave slave;
diff --git a/drivers/spi/sh_qspi.c b/drivers/spi/sh_qspi.c
index 77ede6b..7209e1d 100644
--- a/drivers/spi/sh_qspi.c
+++ b/drivers/spi/sh_qspi.c
@@ -21,19 +21,19 @@
 #define SPPCR_IO3FV	0x04
 #define SPPCR_IO2FV	0x02
 #define SPPCR_IO1FV	0x01
-#define SPBDCR_RXBC0	(1 << 0)
-#define SPCMD_SCKDEN	(1 << 15)
-#define SPCMD_SLNDEN	(1 << 14)
-#define SPCMD_SPNDEN	(1 << 13)
-#define SPCMD_SSLKP	(1 << 7)
-#define SPCMD_BRDV0	(1 << 2)
+#define SPBDCR_RXBC0	BIT(0)
+#define SPCMD_SCKDEN	BIT(15)
+#define SPCMD_SLNDEN	BIT(14)
+#define SPCMD_SPNDEN	BIT(13)
+#define SPCMD_SSLKP	BIT(7)
+#define SPCMD_BRDV0	BIT(2)
 #define SPCMD_INIT1	SPCMD_SCKDEN | SPCMD_SLNDEN | \
 			SPCMD_SPNDEN | SPCMD_SSLKP | \
 			SPCMD_BRDV0
 #define SPCMD_INIT2	SPCMD_SPNDEN | SPCMD_SSLKP | \
 			SPCMD_BRDV0
-#define SPBFCR_TXRST	(1 << 7)
-#define SPBFCR_RXRST	(1 << 6)
+#define SPBFCR_TXRST	BIT(7)
+#define SPBFCR_RXRST	BIT(6)
 
 /* SH QSPI register set */
 struct sh_qspi_regs {
diff --git a/drivers/spi/soft_spi.c b/drivers/spi/soft_spi.c
index 6ae45f5..aa4abcc 100644
--- a/drivers/spi/soft_spi.c
+++ b/drivers/spi/soft_spi.c
@@ -200,7 +200,7 @@
 
 static int soft_spi_probe(struct udevice *dev)
 {
-	struct spi_slave *slave = dev_get_parentdata(dev);
+	struct spi_slave *slave = dev_get_parent_priv(dev);
 	struct soft_spi_platdata *plat = dev->platdata;
 	int cs_flags, clk_flags;
 
diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c
index d666272..58388ef 100644
--- a/drivers/spi/spi-uclass.c
+++ b/drivers/spi/spi-uclass.c
@@ -124,7 +124,7 @@
 static int spi_child_pre_probe(struct udevice *dev)
 {
 	struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev);
-	struct spi_slave *slave = dev_get_parentdata(dev);
+	struct spi_slave *slave = dev_get_parent_priv(dev);
 
 	/*
 	 * This is needed because we pass struct spi_slave around the place
@@ -282,7 +282,7 @@
 		ret = device_probe(dev);
 		if (ret)
 			goto err;
-		slave = dev_get_parentdata(dev);
+		slave = dev_get_parent_priv(dev);
 		slave->dev = dev;
 	}
 
@@ -291,7 +291,7 @@
 		goto err;
 
 	*busp = bus;
-	*devp = dev_get_parentdata(dev);
+	*devp = dev_get_parent_priv(dev);
 	debug("%s: bus=%p, slave=%p\n", __func__, bus, *devp);
 
 	return 0;
@@ -320,7 +320,7 @@
 	ret = device_get_child_by_of_offset(bus, node, &dev);
 	if (ret)
 		return NULL;
-	return dev_get_parentdata(dev);
+	return dev_get_parent_priv(dev);
 }
 
 /* Compatibility function - to be removed */
diff --git a/drivers/spi/tegra114_spi.c b/drivers/spi/tegra114_spi.c
index a965f80..98a062c 100644
--- a/drivers/spi/tegra114_spi.c
+++ b/drivers/spi/tegra114_spi.c
@@ -33,54 +33,54 @@
 DECLARE_GLOBAL_DATA_PTR;
 
 /* COMMAND1 */
-#define SPI_CMD1_GO			(1 << 31)
-#define SPI_CMD1_M_S			(1 << 30)
-#define SPI_CMD1_MODE_MASK		0x3
+#define SPI_CMD1_GO			BIT(31)
+#define SPI_CMD1_M_S			BIT(30)
+#define SPI_CMD1_MODE_MASK		GENMASK(1, 0)
 #define SPI_CMD1_MODE_SHIFT		28
-#define SPI_CMD1_CS_SEL_MASK		0x3
+#define SPI_CMD1_CS_SEL_MASK		GENMASK(1, 0)
 #define SPI_CMD1_CS_SEL_SHIFT		26
-#define SPI_CMD1_CS_POL_INACTIVE3	(1 << 25)
-#define SPI_CMD1_CS_POL_INACTIVE2	(1 << 24)
-#define SPI_CMD1_CS_POL_INACTIVE1	(1 << 23)
-#define SPI_CMD1_CS_POL_INACTIVE0	(1 << 22)
-#define SPI_CMD1_CS_SW_HW		(1 << 21)
-#define SPI_CMD1_CS_SW_VAL		(1 << 20)
-#define SPI_CMD1_IDLE_SDA_MASK		0x3
+#define SPI_CMD1_CS_POL_INACTIVE3	BIT(25)
+#define SPI_CMD1_CS_POL_INACTIVE2	BIT(24)
+#define SPI_CMD1_CS_POL_INACTIVE1	BIT(23)
+#define SPI_CMD1_CS_POL_INACTIVE0	BIT(22)
+#define SPI_CMD1_CS_SW_HW		BIT(21)
+#define SPI_CMD1_CS_SW_VAL		BIT(20)
+#define SPI_CMD1_IDLE_SDA_MASK		GENMASK(1, 0)
 #define SPI_CMD1_IDLE_SDA_SHIFT		18
-#define SPI_CMD1_BIDIR			(1 << 17)
-#define SPI_CMD1_LSBI_FE		(1 << 16)
-#define SPI_CMD1_LSBY_FE		(1 << 15)
-#define SPI_CMD1_BOTH_EN_BIT		(1 << 14)
-#define SPI_CMD1_BOTH_EN_BYTE		(1 << 13)
-#define SPI_CMD1_RX_EN			(1 << 12)
-#define SPI_CMD1_TX_EN			(1 << 11)
-#define SPI_CMD1_PACKED			(1 << 5)
-#define SPI_CMD1_BIT_LEN_MASK		0x1F
+#define SPI_CMD1_BIDIR			BIT(17)
+#define SPI_CMD1_LSBI_FE		BIT(16)
+#define SPI_CMD1_LSBY_FE		BIT(15)
+#define SPI_CMD1_BOTH_EN_BIT		BIT(14)
+#define SPI_CMD1_BOTH_EN_BYTE		BIT(13)
+#define SPI_CMD1_RX_EN			BIT(12)
+#define SPI_CMD1_TX_EN			BIT(11)
+#define SPI_CMD1_PACKED			BIT(5)
+#define SPI_CMD1_BIT_LEN_MASK		GENMASK(4, 0)
 #define SPI_CMD1_BIT_LEN_SHIFT		0
 
 /* COMMAND2 */
-#define SPI_CMD2_TX_CLK_TAP_DELAY	(1 << 6)
-#define SPI_CMD2_TX_CLK_TAP_DELAY_MASK	(0x3F << 6)
-#define SPI_CMD2_RX_CLK_TAP_DELAY	(1 << 0)
-#define SPI_CMD2_RX_CLK_TAP_DELAY_MASK	(0x3F << 0)
+#define SPI_CMD2_TX_CLK_TAP_DELAY	BIT(6)
+#define SPI_CMD2_TX_CLK_TAP_DELAY_MASK	GENMASK(11, 6)
+#define SPI_CMD2_RX_CLK_TAP_DELAY	BIT(0)
+#define SPI_CMD2_RX_CLK_TAP_DELAY_MASK	GENMASK(5, 0)
 
 /* TRANSFER STATUS */
-#define SPI_XFER_STS_RDY		(1 << 30)
+#define SPI_XFER_STS_RDY		BIT(30)
 
 /* FIFO STATUS */
-#define SPI_FIFO_STS_CS_INACTIVE	(1 << 31)
-#define SPI_FIFO_STS_FRAME_END		(1 << 30)
-#define SPI_FIFO_STS_RX_FIFO_FLUSH	(1 << 15)
-#define SPI_FIFO_STS_TX_FIFO_FLUSH	(1 << 14)
-#define SPI_FIFO_STS_ERR		(1 << 8)
-#define SPI_FIFO_STS_TX_FIFO_OVF	(1 << 7)
-#define SPI_FIFO_STS_TX_FIFO_UNR	(1 << 6)
-#define SPI_FIFO_STS_RX_FIFO_OVF	(1 << 5)
-#define SPI_FIFO_STS_RX_FIFO_UNR	(1 << 4)
-#define SPI_FIFO_STS_TX_FIFO_FULL	(1 << 3)
-#define SPI_FIFO_STS_TX_FIFO_EMPTY	(1 << 2)
-#define SPI_FIFO_STS_RX_FIFO_FULL	(1 << 1)
-#define SPI_FIFO_STS_RX_FIFO_EMPTY	(1 << 0)
+#define SPI_FIFO_STS_CS_INACTIVE	BIT(31)
+#define SPI_FIFO_STS_FRAME_END		BIT(30)
+#define SPI_FIFO_STS_RX_FIFO_FLUSH	BIT(15)
+#define SPI_FIFO_STS_TX_FIFO_FLUSH	BIT(14)
+#define SPI_FIFO_STS_ERR		BIT(8)
+#define SPI_FIFO_STS_TX_FIFO_OVF	BIT(7)
+#define SPI_FIFO_STS_TX_FIFO_UNR	BIT(6)
+#define SPI_FIFO_STS_RX_FIFO_OVF	BIT(5)
+#define SPI_FIFO_STS_RX_FIFO_UNR	BIT(4)
+#define SPI_FIFO_STS_TX_FIFO_FULL	BIT(3)
+#define SPI_FIFO_STS_TX_FIFO_EMPTY	BIT(2)
+#define SPI_FIFO_STS_RX_FIFO_FULL	BIT(1)
+#define SPI_FIFO_STS_RX_FIFO_EMPTY	BIT(0)
 
 #define SPI_TIMEOUT		1000
 #define TEGRA_SPI_MAX_FREQ	52000000
diff --git a/drivers/spi/tegra20_sflash.c b/drivers/spi/tegra20_sflash.c
index afa0848..6888a96 100644
--- a/drivers/spi/tegra20_sflash.c
+++ b/drivers/spi/tegra20_sflash.c
@@ -20,37 +20,37 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-#define SPI_CMD_GO			(1 << 30)
+#define SPI_CMD_GO			BIT(30)
 #define SPI_CMD_ACTIVE_SCLK_SHIFT	26
 #define SPI_CMD_ACTIVE_SCLK_MASK	(3 << SPI_CMD_ACTIVE_SCLK_SHIFT)
-#define SPI_CMD_CK_SDA			(1 << 21)
+#define SPI_CMD_CK_SDA			BIT(21)
 #define SPI_CMD_ACTIVE_SDA_SHIFT	18
 #define SPI_CMD_ACTIVE_SDA_MASK		(3 << SPI_CMD_ACTIVE_SDA_SHIFT)
-#define SPI_CMD_CS_POL			(1 << 16)
-#define SPI_CMD_TXEN			(1 << 15)
-#define SPI_CMD_RXEN			(1 << 14)
-#define SPI_CMD_CS_VAL			(1 << 13)
-#define SPI_CMD_CS_SOFT			(1 << 12)
-#define SPI_CMD_CS_DELAY		(1 << 9)
-#define SPI_CMD_CS3_EN			(1 << 8)
-#define SPI_CMD_CS2_EN			(1 << 7)
-#define SPI_CMD_CS1_EN			(1 << 6)
-#define SPI_CMD_CS0_EN			(1 << 5)
-#define SPI_CMD_BIT_LENGTH		(1 << 4)
-#define SPI_CMD_BIT_LENGTH_MASK		0x0000001F
+#define SPI_CMD_CS_POL			BIT(16)
+#define SPI_CMD_TXEN			BIT(15)
+#define SPI_CMD_RXEN			BIT(14)
+#define SPI_CMD_CS_VAL			BIT(13)
+#define SPI_CMD_CS_SOFT			BIT(12)
+#define SPI_CMD_CS_DELAY		BIT(9)
+#define SPI_CMD_CS3_EN			BIT(8)
+#define SPI_CMD_CS2_EN			BIT(7)
+#define SPI_CMD_CS1_EN			BIT(6)
+#define SPI_CMD_CS0_EN			BIT(5)
+#define SPI_CMD_BIT_LENGTH		BIT(4)
+#define SPI_CMD_BIT_LENGTH_MASK		GENMASK(4, 0)
 
-#define SPI_STAT_BSY			(1 << 31)
-#define SPI_STAT_RDY			(1 << 30)
-#define SPI_STAT_RXF_FLUSH		(1 << 29)
-#define SPI_STAT_TXF_FLUSH		(1 << 28)
-#define SPI_STAT_RXF_UNR		(1 << 27)
-#define SPI_STAT_TXF_OVF		(1 << 26)
-#define SPI_STAT_RXF_EMPTY		(1 << 25)
-#define SPI_STAT_RXF_FULL		(1 << 24)
-#define SPI_STAT_TXF_EMPTY		(1 << 23)
-#define SPI_STAT_TXF_FULL		(1 << 22)
-#define SPI_STAT_SEL_TXRX_N		(1 << 16)
-#define SPI_STAT_CUR_BLKCNT		(1 << 15)
+#define SPI_STAT_BSY			BIT(31)
+#define SPI_STAT_RDY			BIT(30)
+#define SPI_STAT_RXF_FLUSH		BIT(29)
+#define SPI_STAT_TXF_FLUSH		BIT(28)
+#define SPI_STAT_RXF_UNR		BIT(27)
+#define SPI_STAT_TXF_OVF		BIT(26)
+#define SPI_STAT_RXF_EMPTY		BIT(25)
+#define SPI_STAT_RXF_FULL		BIT(24)
+#define SPI_STAT_TXF_EMPTY		BIT(23)
+#define SPI_STAT_TXF_FULL		BIT(22)
+#define SPI_STAT_SEL_TXRX_N		BIT(16)
+#define SPI_STAT_CUR_BLKCNT		BIT(15)
 
 #define SPI_TIMEOUT		1000
 #define TEGRA_SPI_MAX_FREQ	52000000
diff --git a/drivers/spi/tegra20_slink.c b/drivers/spi/tegra20_slink.c
index 144716f..43054f1 100644
--- a/drivers/spi/tegra20_slink.c
+++ b/drivers/spi/tegra20_slink.c
@@ -33,45 +33,45 @@
 DECLARE_GLOBAL_DATA_PTR;
 
 /* COMMAND */
-#define SLINK_CMD_ENB			(1 << 31)
-#define SLINK_CMD_GO			(1 << 30)
-#define SLINK_CMD_M_S			(1 << 28)
+#define SLINK_CMD_ENB			BIT(31)
+#define SLINK_CMD_GO			BIT(30)
+#define SLINK_CMD_M_S			BIT(28)
 #define SLINK_CMD_IDLE_SCLK_DRIVE_LOW	(0 << 24)
-#define SLINK_CMD_IDLE_SCLK_DRIVE_HIGH	(1 << 24)
+#define SLINK_CMD_IDLE_SCLK_DRIVE_HIGH	BIT(24)
 #define SLINK_CMD_IDLE_SCLK_PULL_LOW	(2 << 24)
 #define SLINK_CMD_IDLE_SCLK_PULL_HIGH	(3 << 24)
 #define SLINK_CMD_IDLE_SCLK_MASK	(3 << 24)
-#define SLINK_CMD_CK_SDA		(1 << 21)
-#define SLINK_CMD_CS_POL		(1 << 13)
-#define SLINK_CMD_CS_VAL		(1 << 12)
-#define SLINK_CMD_CS_SOFT		(1 << 11)
-#define SLINK_CMD_BIT_LENGTH		(1 << 4)
-#define SLINK_CMD_BIT_LENGTH_MASK	0x0000001F
+#define SLINK_CMD_CK_SDA		BIT(21)
+#define SLINK_CMD_CS_POL		BIT(13)
+#define SLINK_CMD_CS_VAL		BIT(12)
+#define SLINK_CMD_CS_SOFT		BIT(11)
+#define SLINK_CMD_BIT_LENGTH		BIT(4)
+#define SLINK_CMD_BIT_LENGTH_MASK	GENMASK(4, 0)
 /* COMMAND2 */
-#define SLINK_CMD2_TXEN			(1 << 30)
-#define SLINK_CMD2_RXEN			(1 << 31)
-#define SLINK_CMD2_SS_EN		(1 << 18)
+#define SLINK_CMD2_TXEN			BIT(30)
+#define SLINK_CMD2_RXEN			BIT(31)
+#define SLINK_CMD2_SS_EN		BIT(18)
 #define SLINK_CMD2_SS_EN_SHIFT		18
-#define SLINK_CMD2_SS_EN_MASK		0x000C0000
-#define SLINK_CMD2_CS_ACTIVE_BETWEEN	(1 << 17)
+#define SLINK_CMD2_SS_EN_MASK		GENMASK(19, 18)
+#define SLINK_CMD2_CS_ACTIVE_BETWEEN	BIT(17)
 /* STATUS */
-#define SLINK_STAT_BSY			(1 << 31)
-#define SLINK_STAT_RDY			(1 << 30)
-#define SLINK_STAT_ERR			(1 << 29)
-#define SLINK_STAT_RXF_FLUSH		(1 << 27)
-#define SLINK_STAT_TXF_FLUSH		(1 << 26)
-#define SLINK_STAT_RXF_OVF		(1 << 25)
-#define SLINK_STAT_TXF_UNR		(1 << 24)
-#define SLINK_STAT_RXF_EMPTY		(1 << 23)
-#define SLINK_STAT_RXF_FULL		(1 << 22)
-#define SLINK_STAT_TXF_EMPTY		(1 << 21)
-#define SLINK_STAT_TXF_FULL		(1 << 20)
-#define SLINK_STAT_TXF_OVF		(1 << 19)
-#define SLINK_STAT_RXF_UNR		(1 << 18)
-#define SLINK_STAT_CUR_BLKCNT		(1 << 15)
+#define SLINK_STAT_BSY			BIT(31)
+#define SLINK_STAT_RDY			BIT(30)
+#define SLINK_STAT_ERR			BIT(29)
+#define SLINK_STAT_RXF_FLUSH		BIT(27)
+#define SLINK_STAT_TXF_FLUSH		BIT(26)
+#define SLINK_STAT_RXF_OVF		BIT(25)
+#define SLINK_STAT_TXF_UNR		BIT(24)
+#define SLINK_STAT_RXF_EMPTY		BIT(23)
+#define SLINK_STAT_RXF_FULL		BIT(22)
+#define SLINK_STAT_TXF_EMPTY		BIT(21)
+#define SLINK_STAT_TXF_FULL		BIT(20)
+#define SLINK_STAT_TXF_OVF		BIT(19)
+#define SLINK_STAT_RXF_UNR		BIT(18)
+#define SLINK_STAT_CUR_BLKCNT		BIT(15)
 /* STATUS2 */
-#define SLINK_STAT2_RXF_FULL_CNT	(1 << 16)
-#define SLINK_STAT2_TXF_FULL_CNT	(1 << 0)
+#define SLINK_STAT2_RXF_FULL_CNT	BIT(16)
+#define SLINK_STAT2_TXF_FULL_CNT	BIT(0)
 
 #define SPI_TIMEOUT		1000
 #define TEGRA_SPI_MAX_FREQ	52000000
diff --git a/drivers/spi/ti_qspi.c b/drivers/spi/ti_qspi.c
index bd63db8..ecd9d78 100644
--- a/drivers/spi/ti_qspi.c
+++ b/drivers/spi/ti_qspi.c
@@ -20,13 +20,13 @@
 #define QSPI_TIMEOUT                    2000000
 #define QSPI_FCLK                       192000000
 /* clock control */
-#define QSPI_CLK_EN                     (1 << 31)
+#define QSPI_CLK_EN                     BIT(31)
 #define QSPI_CLK_DIV_MAX                0xffff
 /* command */
 #define QSPI_EN_CS(n)                   (n << 28)
 #define QSPI_WLEN(n)                    ((n-1) << 19)
-#define QSPI_3_PIN                      (1 << 18)
-#define QSPI_RD_SNGL                    (1 << 16)
+#define QSPI_3_PIN                      BIT(18)
+#define QSPI_RD_SNGL                    BIT(16)
 #define QSPI_WR_SNGL                    (2 << 16)
 #define QSPI_INVAL                      (4 << 16)
 #define QSPI_RD_QUAD                    (7 << 16)
@@ -36,8 +36,8 @@
 #define QSPI_CSPOL(n)                   (1 << (1 + n*8))
 #define QSPI_CKPOL(n)                   (1 << (n*8))
 /* status */
-#define QSPI_WC                         (1 << 1)
-#define QSPI_BUSY                       (1 << 0)
+#define QSPI_WC                         BIT(1)
+#define QSPI_BUSY                       BIT(0)
 #define QSPI_WC_BUSY                    (QSPI_WC | QSPI_BUSY)
 #define QSPI_XFER_DONE                  QSPI_WC
 #define MM_SWITCH                       0x01
diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c
index 8ccc578..0713714 100644
--- a/drivers/spi/xilinx_spi.c
+++ b/drivers/spi/xilinx_spi.c
@@ -32,34 +32,34 @@
  */
 
 /* SPI Control Register (spicr), [1] p9, [2] p8 */
-#define SPICR_LSB_FIRST		(1 << 9)
-#define SPICR_MASTER_INHIBIT	(1 << 8)
-#define SPICR_MANUAL_SS		(1 << 7)
-#define SPICR_RXFIFO_RESEST	(1 << 6)
-#define SPICR_TXFIFO_RESEST	(1 << 5)
-#define SPICR_CPHA		(1 << 4)
-#define SPICR_CPOL		(1 << 3)
-#define SPICR_MASTER_MODE	(1 << 2)
-#define SPICR_SPE		(1 << 1)
-#define SPICR_LOOP		(1 << 0)
+#define SPICR_LSB_FIRST		BIT(9)
+#define SPICR_MASTER_INHIBIT	BIT(8)
+#define SPICR_MANUAL_SS		BIT(7)
+#define SPICR_RXFIFO_RESEST	BIT(6)
+#define SPICR_TXFIFO_RESEST	BIT(5)
+#define SPICR_CPHA		BIT(4)
+#define SPICR_CPOL		BIT(3)
+#define SPICR_MASTER_MODE	BIT(2)
+#define SPICR_SPE		BIT(1)
+#define SPICR_LOOP		BIT(0)
 
 /* SPI Status Register (spisr), [1] p11, [2] p10 */
-#define SPISR_SLAVE_MODE_SELECT	(1 << 5)
-#define SPISR_MODF		(1 << 4)
-#define SPISR_TX_FULL		(1 << 3)
-#define SPISR_TX_EMPTY		(1 << 2)
-#define SPISR_RX_FULL		(1 << 1)
-#define SPISR_RX_EMPTY		(1 << 0)
+#define SPISR_SLAVE_MODE_SELECT	BIT(5)
+#define SPISR_MODF		BIT(4)
+#define SPISR_TX_FULL		BIT(3)
+#define SPISR_TX_EMPTY		BIT(2)
+#define SPISR_RX_FULL		BIT(1)
+#define SPISR_RX_EMPTY		BIT(0)
 
 /* SPI Data Transmit Register (spidtr), [1] p12, [2] p12 */
-#define SPIDTR_8BIT_MASK	(0xff << 0)
-#define SPIDTR_16BIT_MASK	(0xffff << 0)
-#define SPIDTR_32BIT_MASK	(0xffffffff << 0)
+#define SPIDTR_8BIT_MASK	GENMASK(7, 0)
+#define SPIDTR_16BIT_MASK	GENMASK(15, 0)
+#define SPIDTR_32BIT_MASK	GENMASK(31, 0)
 
 /* SPI Data Receive Register (spidrr), [1] p12, [2] p12 */
-#define SPIDRR_8BIT_MASK	(0xff << 0)
-#define SPIDRR_16BIT_MASK	(0xffff << 0)
-#define SPIDRR_32BIT_MASK	(0xffffffff << 0)
+#define SPIDRR_8BIT_MASK	GENMASK(7, 0)
+#define SPIDRR_16BIT_MASK	GENMASK(15, 0)
+#define SPIDRR_32BIT_MASK	GENMASK(31, 0)
 
 /* SPI Slave Select Register (spissr), [1] p13, [2] p13 */
 #define SPISSR_MASK(cs)		(1 << (cs))
@@ -75,7 +75,7 @@
 #define XILSPI_SPICR_DFLT_OFF	(SPICR_MASTER_INHIBIT | SPICR_MANUAL_SS)
 
 #ifndef CONFIG_XILINX_SPI_IDLE_VAL
-#define CONFIG_XILINX_SPI_IDLE_VAL	0xff
+#define CONFIG_XILINX_SPI_IDLE_VAL	GENMASK(7, 0)
 #endif
 
 #ifndef CONFIG_SYS_XILINX_SPI_LIST
diff --git a/drivers/spi/zynq_qspi.c b/drivers/spi/zynq_qspi.c
new file mode 100644
index 0000000..5825c6d
--- /dev/null
+++ b/drivers/spi/zynq_qspi.c
@@ -0,0 +1,621 @@
+/*
+ * (C) Copyright 2013 Xilinx, Inc.
+ * (C) Copyright 2015 Jagan Teki <jteki@openedev.com>
+ *
+ * Xilinx Zynq Quad-SPI(QSPI) controller driver (master mode only)
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <malloc.h>
+#include <spi.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* zynq qspi register bit masks ZYNQ_QSPI_<REG>_<BIT>_MASK */
+#define ZYNQ_QSPI_CR_IFMODE_MASK	BIT(31)	/* Flash intrface mode*/
+#define ZYNQ_QSPI_CR_MSA_MASK		BIT(15)	/* Manual start enb */
+#define ZYNQ_QSPI_CR_MCS_MASK		BIT(14)	/* Manual chip select */
+#define ZYNQ_QSPI_CR_PCS_MASK		BIT(10)	/* Peri chip select */
+#define ZYNQ_QSPI_CR_FW_MASK		GENMASK(7, 6)	/* FIFO width */
+#define ZYNQ_QSPI_CR_SS_MASK		GENMASK(13, 10)	/* Slave Select */
+#define ZYNQ_QSPI_CR_BAUD_MASK		GENMASK(5, 3)	/* Baud rate div */
+#define ZYNQ_QSPI_CR_CPHA_MASK		BIT(2)	/* Clock phase */
+#define ZYNQ_QSPI_CR_CPOL_MASK		BIT(1)	/* Clock polarity */
+#define ZYNQ_QSPI_CR_MSTREN_MASK	BIT(0)	/* Mode select */
+#define ZYNQ_QSPI_IXR_RXNEMPTY_MASK	BIT(4)	/* RX_FIFO_not_empty */
+#define ZYNQ_QSPI_IXR_TXOW_MASK		BIT(2)	/* TX_FIFO_not_full */
+#define ZYNQ_QSPI_IXR_ALL_MASK		GENMASK(6, 0)	/* All IXR bits */
+#define ZYNQ_QSPI_ENR_SPI_EN_MASK	BIT(0)	/* SPI Enable */
+
+/* zynq qspi Transmit Data Register */
+#define ZYNQ_QSPI_TXD_00_00_OFFSET	0x1C	/* Transmit 4-byte inst */
+#define ZYNQ_QSPI_TXD_00_01_OFFSET	0x80	/* Transmit 1-byte inst */
+#define ZYNQ_QSPI_TXD_00_10_OFFSET	0x84	/* Transmit 2-byte inst */
+#define ZYNQ_QSPI_TXD_00_11_OFFSET	0x88	/* Transmit 3-byte inst */
+
+#define ZYNQ_QSPI_TXFIFO_THRESHOLD	1	/* Tx FIFO threshold level*/
+#define ZYNQ_QSPI_RXFIFO_THRESHOLD	32	/* Rx FIFO threshold level */
+
+#define ZYNQ_QSPI_CR_BAUD_MAX		8	/* Baud rate divisor max val */
+#define ZYNQ_QSPI_CR_BAUD_SHIFT		3	/* Baud rate divisor shift */
+#define ZYNQ_QSPI_CR_SS_SHIFT		10	/* Slave select shift */
+
+#define ZYNQ_QSPI_FIFO_DEPTH		63
+#ifndef CONFIG_SYS_ZYNQ_QSPI_WAIT
+#define CONFIG_SYS_ZYNQ_QSPI_WAIT	CONFIG_SYS_HZ/100	/* 10 ms */
+#endif
+
+/* zynq qspi register set */
+struct zynq_qspi_regs {
+	u32 cr;		/* 0x00 */
+	u32 isr;	/* 0x04 */
+	u32 ier;	/* 0x08 */
+	u32 idr;	/* 0x0C */
+	u32 imr;	/* 0x10 */
+	u32 enr;	/* 0x14 */
+	u32 dr;		/* 0x18 */
+	u32 txd0r;	/* 0x1C */
+	u32 drxr;	/* 0x20 */
+	u32 sicr;	/* 0x24 */
+	u32 txftr;	/* 0x28 */
+	u32 rxftr;	/* 0x2C */
+	u32 gpior;	/* 0x30 */
+	u32 reserved0[19];
+	u32 txd1r;	/* 0x80 */
+	u32 txd2r;	/* 0x84 */
+	u32 txd3r;	/* 0x88 */
+};
+
+/* zynq qspi platform data */
+struct zynq_qspi_platdata {
+	struct zynq_qspi_regs *regs;
+	u32 frequency;          /* input frequency */
+	u32 speed_hz;
+};
+
+/* zynq qspi priv */
+struct zynq_qspi_priv {
+	struct zynq_qspi_regs *regs;
+	u8 cs;
+	u8 mode;
+	u8 fifo_depth;
+	u32 freq;		/* required frequency */
+	const void *tx_buf;
+	void *rx_buf;
+	unsigned len;
+	int bytes_to_transfer;
+	int bytes_to_receive;
+	unsigned int is_inst;
+	unsigned cs_change:1;
+};
+
+static int zynq_qspi_ofdata_to_platdata(struct udevice *bus)
+{
+	struct zynq_qspi_platdata *plat = bus->platdata;
+	const void *blob = gd->fdt_blob;
+	int node = bus->of_offset;
+
+	plat->regs = (struct zynq_qspi_regs *)fdtdec_get_addr(blob,
+							      node, "reg");
+
+	/* FIXME: Use 166MHz as a suitable default */
+	plat->frequency = fdtdec_get_int(blob, node, "spi-max-frequency",
+					166666666);
+	plat->speed_hz = plat->frequency / 2;
+
+	debug("%s: regs=%p max-frequency=%d\n", __func__,
+	      plat->regs, plat->frequency);
+
+	return 0;
+}
+
+static void zynq_qspi_init_hw(struct zynq_qspi_priv *priv)
+{
+	struct zynq_qspi_regs *regs = priv->regs;
+	u32 confr;
+
+	/* Disable QSPI */
+	writel(~ZYNQ_QSPI_ENR_SPI_EN_MASK, &regs->enr);
+
+	/* Disable Interrupts */
+	writel(ZYNQ_QSPI_IXR_ALL_MASK, &regs->idr);
+
+	/* Clear the TX and RX threshold reg */
+	writel(ZYNQ_QSPI_TXFIFO_THRESHOLD, &regs->txftr);
+	writel(ZYNQ_QSPI_RXFIFO_THRESHOLD, &regs->rxftr);
+
+	/* Clear the RX FIFO */
+	while (readl(&regs->isr) & ZYNQ_QSPI_IXR_RXNEMPTY_MASK)
+		readl(&regs->drxr);
+
+	/* Clear Interrupts */
+	writel(ZYNQ_QSPI_IXR_ALL_MASK, &regs->isr);
+
+	/* Manual slave select and Auto start */
+	confr = readl(&regs->cr);
+	confr &= ~ZYNQ_QSPI_CR_MSA_MASK;
+	confr |= ZYNQ_QSPI_CR_IFMODE_MASK | ZYNQ_QSPI_CR_MCS_MASK |
+		ZYNQ_QSPI_CR_PCS_MASK | ZYNQ_QSPI_CR_FW_MASK |
+		ZYNQ_QSPI_CR_MSTREN_MASK;
+	writel(confr, &regs->cr);
+
+	/* Enable SPI */
+	writel(ZYNQ_QSPI_ENR_SPI_EN_MASK, &regs->enr);
+}
+
+static int zynq_qspi_probe(struct udevice *bus)
+{
+	struct zynq_qspi_platdata *plat = dev_get_platdata(bus);
+	struct zynq_qspi_priv *priv = dev_get_priv(bus);
+
+	priv->regs = plat->regs;
+	priv->fifo_depth = ZYNQ_QSPI_FIFO_DEPTH;
+
+	/* init the zynq spi hw */
+	zynq_qspi_init_hw(priv);
+
+	return 0;
+}
+
+/*
+ * zynq_qspi_read_data - Copy data to RX buffer
+ * @zqspi:	Pointer to the zynq_qspi structure
+ * @data:	The 32 bit variable where data is stored
+ * @size:	Number of bytes to be copied from data to RX buffer
+ */
+static void zynq_qspi_read_data(struct zynq_qspi_priv *priv, u32 data, u8 size)
+{
+	u8 byte3;
+
+	debug("%s: data 0x%04x rx_buf addr: 0x%08x size %d\n", __func__ ,
+	      data, (unsigned)(priv->rx_buf), size);
+
+	if (priv->rx_buf) {
+		switch (size) {
+		case 1:
+			*((u8 *)priv->rx_buf) = data;
+			priv->rx_buf += 1;
+			break;
+		case 2:
+			*((u16 *)priv->rx_buf) = data;
+			priv->rx_buf += 2;
+			break;
+		case 3:
+			*((u16 *)priv->rx_buf) = data;
+			priv->rx_buf += 2;
+			byte3 = (u8)(data >> 16);
+			*((u8 *)priv->rx_buf) = byte3;
+			priv->rx_buf += 1;
+			break;
+		case 4:
+			/* Can not assume word aligned buffer */
+			memcpy(priv->rx_buf, &data, size);
+			priv->rx_buf += 4;
+			break;
+		default:
+			/* This will never execute */
+			break;
+		}
+	}
+	priv->bytes_to_receive -= size;
+	if (priv->bytes_to_receive < 0)
+		priv->bytes_to_receive = 0;
+}
+
+/*
+ * zynq_qspi_write_data - Copy data from TX buffer
+ * @zqspi:	Pointer to the zynq_qspi structure
+ * @data:	Pointer to the 32 bit variable where data is to be copied
+ * @size:	Number of bytes to be copied from TX buffer to data
+ */
+static void zynq_qspi_write_data(struct  zynq_qspi_priv *priv,
+		u32 *data, u8 size)
+{
+	if (priv->tx_buf) {
+		switch (size) {
+		case 1:
+			*data = *((u8 *)priv->tx_buf);
+			priv->tx_buf += 1;
+			*data |= 0xFFFFFF00;
+			break;
+		case 2:
+			*data = *((u16 *)priv->tx_buf);
+			priv->tx_buf += 2;
+			*data |= 0xFFFF0000;
+			break;
+		case 3:
+			*data = *((u16 *)priv->tx_buf);
+			priv->tx_buf += 2;
+			*data |= (*((u8 *)priv->tx_buf) << 16);
+			priv->tx_buf += 1;
+			*data |= 0xFF000000;
+			break;
+		case 4:
+			/* Can not assume word aligned buffer */
+			memcpy(data, priv->tx_buf, size);
+			priv->tx_buf += 4;
+			break;
+		default:
+			/* This will never execute */
+			break;
+		}
+	} else {
+		*data = 0;
+	}
+
+	debug("%s: data 0x%08x tx_buf addr: 0x%08x size %d\n", __func__,
+	      *data, (u32)priv->tx_buf, size);
+
+	priv->bytes_to_transfer -= size;
+	if (priv->bytes_to_transfer < 0)
+		priv->bytes_to_transfer = 0;
+}
+
+static void zynq_qspi_chipselect(struct  zynq_qspi_priv *priv, int is_on)
+{
+	u32 confr;
+	struct zynq_qspi_regs *regs = priv->regs;
+
+	confr = readl(&regs->cr);
+
+	if (is_on) {
+		/* Select the slave */
+		confr &= ~ZYNQ_QSPI_CR_SS_MASK;
+		confr |= (~(1 << priv->cs) << ZYNQ_QSPI_CR_SS_SHIFT) &
+					ZYNQ_QSPI_CR_SS_MASK;
+	} else
+		/* Deselect the slave */
+		confr |= ZYNQ_QSPI_CR_SS_MASK;
+
+	writel(confr, &regs->cr);
+}
+
+/*
+ * zynq_qspi_fill_tx_fifo - Fills the TX FIFO with as many bytes as possible
+ * @zqspi:	Pointer to the zynq_qspi structure
+ */
+static void zynq_qspi_fill_tx_fifo(struct zynq_qspi_priv *priv, u32 size)
+{
+	u32 data = 0;
+	u32 fifocount = 0;
+	unsigned len, offset;
+	struct zynq_qspi_regs *regs = priv->regs;
+	static const unsigned offsets[4] = {
+		ZYNQ_QSPI_TXD_00_00_OFFSET, ZYNQ_QSPI_TXD_00_01_OFFSET,
+		ZYNQ_QSPI_TXD_00_10_OFFSET, ZYNQ_QSPI_TXD_00_11_OFFSET };
+
+	while ((fifocount < size) &&
+			(priv->bytes_to_transfer > 0)) {
+		if (priv->bytes_to_transfer >= 4) {
+			if (priv->tx_buf) {
+				memcpy(&data, priv->tx_buf, 4);
+				priv->tx_buf += 4;
+			} else {
+				data = 0;
+			}
+			writel(data, &regs->txd0r);
+			priv->bytes_to_transfer -= 4;
+			fifocount++;
+		} else {
+			/* Write TXD1, TXD2, TXD3 only if TxFIFO is empty. */
+			if (!(readl(&regs->isr)
+					& ZYNQ_QSPI_IXR_TXOW_MASK) &&
+					!priv->rx_buf)
+				return;
+			len = priv->bytes_to_transfer;
+			zynq_qspi_write_data(priv, &data, len);
+			offset = (priv->rx_buf) ? offsets[0] : offsets[len];
+			writel(data, &regs->cr + (offset / 4));
+		}
+	}
+}
+
+/*
+ * zynq_qspi_irq_poll - Interrupt service routine of the QSPI controller
+ * @zqspi:	Pointer to the zynq_qspi structure
+ *
+ * This function handles TX empty and Mode Fault interrupts only.
+ * On TX empty interrupt this function reads the received data from RX FIFO and
+ * fills the TX FIFO if there is any data remaining to be transferred.
+ * On Mode Fault interrupt this function indicates that transfer is completed,
+ * the SPI subsystem will identify the error as the remaining bytes to be
+ * transferred is non-zero.
+ *
+ * returns:	0 for poll timeout
+ *		1 transfer operation complete
+ */
+static int zynq_qspi_irq_poll(struct zynq_qspi_priv *priv)
+{
+	struct zynq_qspi_regs *regs = priv->regs;
+	u32 rxindex = 0;
+	u32 rxcount;
+	u32 status, timeout;
+
+	/* Poll until any of the interrupt status bits are set */
+	timeout = get_timer(0);
+	do {
+		status = readl(&regs->isr);
+	} while ((status == 0) &&
+		(get_timer(timeout) < CONFIG_SYS_ZYNQ_QSPI_WAIT));
+
+	if (status == 0) {
+		printf("zynq_qspi_irq_poll: Timeout!\n");
+		return -ETIMEDOUT;
+	}
+
+	writel(status, &regs->isr);
+
+	/* Disable all interrupts */
+	writel(ZYNQ_QSPI_IXR_ALL_MASK, &regs->idr);
+	if ((status & ZYNQ_QSPI_IXR_TXOW_MASK) ||
+	    (status & ZYNQ_QSPI_IXR_RXNEMPTY_MASK)) {
+		/*
+		 * This bit is set when Tx FIFO has < THRESHOLD entries. We have
+		 * the THRESHOLD value set to 1, so this bit indicates Tx FIFO
+		 * is empty
+		 */
+		rxcount = priv->bytes_to_receive - priv->bytes_to_transfer;
+		rxcount = (rxcount % 4) ? ((rxcount/4)+1) : (rxcount/4);
+		while ((rxindex < rxcount) &&
+				(rxindex < ZYNQ_QSPI_RXFIFO_THRESHOLD)) {
+			/* Read out the data from the RX FIFO */
+			u32 data;
+			data = readl(&regs->drxr);
+
+			if (priv->bytes_to_receive >= 4) {
+				if (priv->rx_buf) {
+					memcpy(priv->rx_buf, &data, 4);
+					priv->rx_buf += 4;
+				}
+				priv->bytes_to_receive -= 4;
+			} else {
+				zynq_qspi_read_data(priv, data,
+						    priv->bytes_to_receive);
+			}
+			rxindex++;
+		}
+
+		if (priv->bytes_to_transfer) {
+			/* There is more data to send */
+			zynq_qspi_fill_tx_fifo(priv,
+					       ZYNQ_QSPI_RXFIFO_THRESHOLD);
+
+			writel(ZYNQ_QSPI_IXR_ALL_MASK, &regs->ier);
+		} else {
+			/*
+			 * If transfer and receive is completed then only send
+			 * complete signal
+			 */
+			if (!priv->bytes_to_receive) {
+				/* return operation complete */
+				writel(ZYNQ_QSPI_IXR_ALL_MASK,
+				       &regs->idr);
+				return 1;
+			}
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * zynq_qspi_start_transfer - Initiates the QSPI transfer
+ * @qspi:	Pointer to the spi_device structure
+ * @transfer:	Pointer to the spi_transfer structure which provide information
+ *		about next transfer parameters
+ *
+ * This function fills the TX FIFO, starts the QSPI transfer, and waits for the
+ * transfer to be completed.
+ *
+ * returns:	Number of bytes transferred in the last transfer
+ */
+static int zynq_qspi_start_transfer(struct zynq_qspi_priv *priv)
+{
+	u32 data = 0;
+	struct zynq_qspi_regs *regs = priv->regs;
+
+	debug("%s: qspi: 0x%08x transfer: 0x%08x len: %d\n", __func__,
+	      (u32)priv, (u32)priv, priv->len);
+
+	priv->bytes_to_transfer = priv->len;
+	priv->bytes_to_receive = priv->len;
+
+	if (priv->len < 4)
+		zynq_qspi_fill_tx_fifo(priv, priv->len);
+	else
+		zynq_qspi_fill_tx_fifo(priv, priv->fifo_depth);
+
+	writel(ZYNQ_QSPI_IXR_ALL_MASK, &regs->ier);
+
+	/* wait for completion */
+	do {
+		data = zynq_qspi_irq_poll(priv);
+	} while (data == 0);
+
+	return (priv->len) - (priv->bytes_to_transfer);
+}
+
+static int zynq_qspi_transfer(struct zynq_qspi_priv *priv)
+{
+	unsigned cs_change = 1;
+	int status = 0;
+
+	while (1) {
+		/* Select the chip if required */
+		if (cs_change)
+			zynq_qspi_chipselect(priv, 1);
+
+		cs_change = priv->cs_change;
+
+		if (!priv->tx_buf && !priv->rx_buf && priv->len) {
+			status = -1;
+			break;
+		}
+
+		/* Request the transfer */
+		if (priv->len) {
+			status = zynq_qspi_start_transfer(priv);
+			priv->is_inst = 0;
+		}
+
+		if (status != priv->len) {
+			if (status > 0)
+				status = -EMSGSIZE;
+			debug("zynq_qspi_transfer:%d len:%d\n",
+			      status, priv->len);
+			break;
+		}
+		status = 0;
+
+		if (cs_change)
+			/* Deselect the chip */
+			zynq_qspi_chipselect(priv, 0);
+
+		break;
+	}
+
+	return 0;
+}
+
+static int zynq_qspi_claim_bus(struct udevice *dev)
+{
+	struct udevice *bus = dev->parent;
+	struct zynq_qspi_priv *priv = dev_get_priv(bus);
+	struct zynq_qspi_regs *regs = priv->regs;
+
+	writel(ZYNQ_QSPI_ENR_SPI_EN_MASK, &regs->enr);
+
+	return 0;
+}
+
+static int zynq_qspi_release_bus(struct udevice *dev)
+{
+	struct udevice *bus = dev->parent;
+	struct zynq_qspi_priv *priv = dev_get_priv(bus);
+	struct zynq_qspi_regs *regs = priv->regs;
+
+	writel(~ZYNQ_QSPI_ENR_SPI_EN_MASK, &regs->enr);
+
+	return 0;
+}
+
+static int zynq_qspi_xfer(struct udevice *dev, unsigned int bitlen,
+		const void *dout, void *din, unsigned long flags)
+{
+	struct udevice *bus = dev->parent;
+	struct zynq_qspi_priv *priv = dev_get_priv(bus);
+	struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
+
+	priv->cs = slave_plat->cs;
+	priv->tx_buf = dout;
+	priv->rx_buf = din;
+	priv->len = bitlen / 8;
+
+	debug("zynq_qspi_xfer: bus:%i cs:%i bitlen:%i len:%i flags:%lx\n",
+	      bus->seq, slave_plat->cs, bitlen, priv->len, flags);
+
+	/*
+	 * Festering sore.
+	 * Assume that the beginning of a transfer with bits to
+	 * transmit must contain a device command.
+	 */
+	if (dout && flags & SPI_XFER_BEGIN)
+		priv->is_inst = 1;
+	else
+		priv->is_inst = 0;
+
+	if (flags & SPI_XFER_END)
+		priv->cs_change = 1;
+	else
+		priv->cs_change = 0;
+
+	zynq_qspi_transfer(priv);
+
+	return 0;
+}
+
+static int zynq_qspi_set_speed(struct udevice *bus, uint speed)
+{
+	struct zynq_qspi_platdata *plat = bus->platdata;
+	struct zynq_qspi_priv *priv = dev_get_priv(bus);
+	struct zynq_qspi_regs *regs = priv->regs;
+	uint32_t confr;
+	u8 baud_rate_val = 0;
+
+	if (speed > plat->frequency)
+		speed = plat->frequency;
+
+	/* Set the clock frequency */
+	confr = readl(&regs->cr);
+	if (speed == 0) {
+		/* Set baudrate x8, if the freq is 0 */
+		baud_rate_val = 0x2;
+	} else if (plat->speed_hz != speed) {
+		while ((baud_rate_val < ZYNQ_QSPI_CR_BAUD_MAX) &&
+		       ((plat->frequency /
+		       (2 << baud_rate_val)) > speed))
+			baud_rate_val++;
+
+		plat->speed_hz = speed / (2 << baud_rate_val);
+	}
+	confr &= ~ZYNQ_QSPI_CR_BAUD_MASK;
+	confr |= (baud_rate_val << ZYNQ_QSPI_CR_BAUD_SHIFT);
+
+	writel(confr, &regs->cr);
+	priv->freq = speed;
+
+	debug("%s: regs=%p, speed=%d\n", __func__, priv->regs, priv->freq);
+
+	return 0;
+}
+
+static int zynq_qspi_set_mode(struct udevice *bus, uint mode)
+{
+	struct zynq_qspi_priv *priv = dev_get_priv(bus);
+	struct zynq_qspi_regs *regs = priv->regs;
+	uint32_t confr;
+
+	/* Set the SPI Clock phase and polarities */
+	confr = readl(&regs->cr);
+	confr &= ~(ZYNQ_QSPI_CR_CPHA_MASK | ZYNQ_QSPI_CR_CPOL_MASK);
+
+	if (mode & SPI_CPHA)
+		confr |= ZYNQ_QSPI_CR_CPHA_MASK;
+	if (mode & SPI_CPOL)
+		confr |= ZYNQ_QSPI_CR_CPOL_MASK;
+
+	writel(confr, &regs->cr);
+	priv->mode = mode;
+
+	debug("%s: regs=%p, mode=%d\n", __func__, priv->regs, priv->mode);
+
+	return 0;
+}
+
+static const struct dm_spi_ops zynq_qspi_ops = {
+	.claim_bus      = zynq_qspi_claim_bus,
+	.release_bus    = zynq_qspi_release_bus,
+	.xfer           = zynq_qspi_xfer,
+	.set_speed      = zynq_qspi_set_speed,
+	.set_mode       = zynq_qspi_set_mode,
+};
+
+static const struct udevice_id zynq_qspi_ids[] = {
+	{ .compatible = "xlnx,zynq-qspi-1.0" },
+	{ }
+};
+
+U_BOOT_DRIVER(zynq_qspi) = {
+	.name   = "zynq_qspi",
+	.id     = UCLASS_SPI,
+	.of_match = zynq_qspi_ids,
+	.ops    = &zynq_qspi_ops,
+	.ofdata_to_platdata = zynq_qspi_ofdata_to_platdata,
+	.platdata_auto_alloc_size = sizeof(struct zynq_qspi_platdata),
+	.priv_auto_alloc_size = sizeof(struct zynq_qspi_priv),
+	.probe  = zynq_qspi_probe,
+};
diff --git a/drivers/spi/zynq_spi.c b/drivers/spi/zynq_spi.c
index d370e49..6ed2165 100644
--- a/drivers/spi/zynq_spi.c
+++ b/drivers/spi/zynq_spi.c
@@ -1,5 +1,5 @@
 /*
- * (C) Copyright 2013 Inc.
+ * (C) Copyright 2013 Xilinx, Inc.
  * (C) Copyright 2015 Jagan Teki <jteki@openedev.com>
  *
  * Xilinx Zynq PS SPI controller driver (master mode only)
@@ -7,30 +7,30 @@
  * SPDX-License-Identifier:     GPL-2.0+
  */
 
-#include <config.h>
 #include <common.h>
 #include <dm.h>
-#include <errno.h>
 #include <malloc.h>
 #include <spi.h>
-#include <fdtdec.h>
 #include <asm/io.h>
-#include <asm/arch/hardware.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
 /* zynq spi register bit masks ZYNQ_SPI_<REG>_<BIT>_MASK */
-#define ZYNQ_SPI_CR_MSA_MASK		(1 << 15)	/* Manual start enb */
-#define ZYNQ_SPI_CR_MCS_MASK		(1 << 14)	/* Manual chip select */
-#define ZYNQ_SPI_CR_CS_MASK		(0xF << 10)	/* Chip select */
-#define ZYNQ_SPI_CR_BRD_MASK		(0x7 << 3)	/* Baud rate div */
-#define ZYNQ_SPI_CR_CPHA_MASK		(1 << 2)	/* Clock phase */
-#define ZYNQ_SPI_CR_CPOL_MASK		(1 << 1)	/* Clock polarity */
-#define ZYNQ_SPI_CR_MSTREN_MASK		(1 << 0)	/* Mode select */
-#define ZYNQ_SPI_IXR_RXNEMPTY_MASK	(1 << 4)	/* RX_FIFO_not_empty */
-#define ZYNQ_SPI_IXR_TXOW_MASK		(1 << 2)	/* TX_FIFO_not_full */
-#define ZYNQ_SPI_IXR_ALL_MASK		0x7F		/* All IXR bits */
-#define ZYNQ_SPI_ENR_SPI_EN_MASK	(1 << 0)	/* SPI Enable */
+#define ZYNQ_SPI_CR_MSA_MASK		BIT(15)	/* Manual start enb */
+#define ZYNQ_SPI_CR_MCS_MASK		BIT(14)	/* Manual chip select */
+#define ZYNQ_SPI_CR_CS_MASK		GENMASK(13, 10)	/* Chip select */
+#define ZYNQ_SPI_CR_BAUD_MASK		GENMASK(5, 3)	/* Baud rate div */
+#define ZYNQ_SPI_CR_CPHA_MASK		BIT(2)	/* Clock phase */
+#define ZYNQ_SPI_CR_CPOL_MASK		BIT(1)	/* Clock polarity */
+#define ZYNQ_SPI_CR_MSTREN_MASK		BIT(0)	/* Mode select */
+#define ZYNQ_SPI_IXR_RXNEMPTY_MASK	BIT(4)	/* RX_FIFO_not_empty */
+#define ZYNQ_SPI_IXR_TXOW_MASK		BIT(2)	/* TX_FIFO_not_full */
+#define ZYNQ_SPI_IXR_ALL_MASK		GENMASK(6, 0)	/* All IXR bits */
+#define ZYNQ_SPI_ENR_SPI_EN_MASK	BIT(0)	/* SPI Enable */
+
+#define ZYNQ_SPI_CR_BAUD_MAX		8	/* Baud rate divisor max val */
+#define ZYNQ_SPI_CR_BAUD_SHIFT		3	/* Baud rate divisor shift */
+#define ZYNQ_SPI_CR_SS_SHIFT		10	/* Slave select shift */
 
 #define ZYNQ_SPI_FIFO_DEPTH		128
 #ifndef CONFIG_SYS_ZYNQ_SPI_WAIT
@@ -61,6 +61,7 @@
 /* zynq spi priv */
 struct zynq_spi_priv {
 	struct zynq_spi_regs *regs;
+	u8 cs;
 	u8 mode;
 	u8 fifo_depth;
 	u32 freq;		/* required frequency */
@@ -128,7 +129,7 @@
 	return 0;
 }
 
-static void spi_cs_activate(struct udevice *dev, uint cs)
+static void spi_cs_activate(struct udevice *dev)
 {
 	struct udevice *bus = dev->parent;
 	struct zynq_spi_priv *priv = dev_get_priv(bus);
@@ -143,7 +144,7 @@
 	 * xx01	- cs1
 	 * x011 - cs2
 	 */
-	cr |= (~(0x1 << cs) << 10) & ZYNQ_SPI_CR_CS_MASK;
+	cr |= (~(1 << priv->cs) << ZYNQ_SPI_CR_SS_SHIFT) & ZYNQ_SPI_CR_CS_MASK;
 	writel(cr, &regs->cr);
 }
 
@@ -199,8 +200,9 @@
 		return -1;
 	}
 
+	priv->cs = slave_plat->cs;
 	if (flags & SPI_XFER_BEGIN)
-		spi_cs_activate(dev, slave_plat->cs);
+		spi_cs_activate(dev);
 
 	while (rx_len > 0) {
 		/* Write the data into TX FIFO - tx threshold is fifo_depth */
@@ -260,14 +262,14 @@
 		/* Set baudrate x8, if the freq is 0 */
 		baud_rate_val = 0x2;
 	} else if (plat->speed_hz != speed) {
-		while ((baud_rate_val < 8) &&
+		while ((baud_rate_val < ZYNQ_SPI_CR_BAUD_MAX) &&
 				((plat->frequency /
 				(2 << baud_rate_val)) > speed))
 			baud_rate_val++;
 		plat->speed_hz = speed / (2 << baud_rate_val);
 	}
-	confr &= ~ZYNQ_SPI_CR_BRD_MASK;
-	confr |= (baud_rate_val << 3);
+	confr &= ~ZYNQ_SPI_CR_BAUD_MASK;
+	confr |= (baud_rate_val << ZYNQ_SPI_CR_BAUD_SHIFT);
 
 	writel(confr, &regs->cr);
 	priv->freq = speed;
diff --git a/drivers/tpm/Kconfig b/drivers/tpm/Kconfig
index 6bc8fdd..31b35f7 100644
--- a/drivers/tpm/Kconfig
+++ b/drivers/tpm/Kconfig
@@ -4,15 +4,6 @@
 
 menu "TPM support"
 
-config DM_TPM
-	bool "Enable driver model for Trusted Platform Module drivers"
-	depends on DM && TPM
-	help
-          Enable driver model for TPMs. The TIS interface (tis_open(),
-	  tis_sendrecv(), etc.) is then implemented by the TPM uclass. Note
-	  that even with driver model only a single TPM is currently
-	  supported, since the tpm library assumes this.
-
 config TPM_TIS_SANDBOX
 	bool "Enable sandbox TPM driver"
 	depends on SANDBOX
@@ -24,14 +15,14 @@
 
 config TPM_ATMEL_TWI
 	bool "Enable Atmel TWI TPM device driver"
-	depends on TPM
+	depends on TPM && DM_I2C
 	help
 	  This driver supports an Atmel TPM device connected on the I2C bus.
 	  The usual tpm operations and the 'tpm' command can be used to talk
 	  to the device using the standard TPM Interface Specification (TIS)
 	  protocol
 
-config TPM_TIS_I2C
+config TPM_TIS_INFINEON
 	bool "Enable support for Infineon SLB9635/45 TPMs on I2C"
 	depends on TPM && DM_I2C
 	help
@@ -42,7 +33,7 @@
 
 config TPM_TIS_I2C_BURST_LIMITATION
 	bool "Enable I2C burst length limitation"
-	depends on TPM_TIS_I2C
+	depends on TPM_TIS_INFINEON
 	help
 	  Some broken TPMs have a limitation on the number of bytes they can
 	  receive in one message. Enable this option to allow you to set this
diff --git a/drivers/tpm/Makefile b/drivers/tpm/Makefile
index 0d328f8..1d49e95 100644
--- a/drivers/tpm/Makefile
+++ b/drivers/tpm/Makefile
@@ -3,9 +3,9 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
-obj-$(CONFIG_DM_TPM) += tpm-uclass.o
+obj-$(CONFIG_TPM) += tpm-uclass.o
 
 obj-$(CONFIG_TPM_ATMEL_TWI) += tpm_atmel_twi.o
-obj-$(CONFIG_TPM_TIS_I2C) += tpm_tis_i2c.o
+obj-$(CONFIG_TPM_TIS_INFINEON) += tpm_tis_infineon.o
 obj-$(CONFIG_TPM_TIS_LPC) += tpm_tis_lpc.o
 obj-$(CONFIG_TPM_TIS_SANDBOX) += tpm_tis_sandbox.o
diff --git a/drivers/tpm/tpm_atmel_twi.c b/drivers/tpm/tpm_atmel_twi.c
index 205d7a5..2aa9381 100644
--- a/drivers/tpm/tpm_atmel_twi.c
+++ b/drivers/tpm/tpm_atmel_twi.c
@@ -7,51 +7,56 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <tpm.h>
 #include <i2c.h>
 #include <asm/unaligned.h>
 
+#include "tpm_internal.h"
+
 #define ATMEL_TPM_TIMEOUT_MS 5000 /* sufficient for anything but
 				     generating/exporting keys */
 
 /*
- * tis_init()
- *
- * Initialize the TPM device. Returns 0 on success or -1 on
- * failure (in case device probing did not succeed).
- */
-int tis_init(void)
-{
-	return 0;
-}
-
-/*
- * tis_open()
+ * tpm_atmel_twi_open()
  *
  * Requests access to locality 0 for the caller. After all commands have been
  * completed the caller is supposed to call tis_close().
  *
  * Returns 0 on success, -1 on failure.
  */
-int tis_open(void)
+static int tpm_atmel_twi_open(struct udevice *dev)
 {
 	return 0;
 }
 
 /*
- * tis_close()
+ * tpm_atmel_twi_close()
  *
  * terminate the currect session with the TPM by releasing the locked
  * locality. Returns 0 on success of -1 on failure (in case lock
  * removal did not succeed).
  */
+static int tpm_atmel_twi_close(struct udevice *dev)
+{
+	return 0;
+}
+
+/*
+ * tpm_atmel_twi_get_desc()
+ *
+ * @dev:        Device to check
+ * @buf:        Buffer to put the string
+ * @size:       Maximum size of buffer
+ * @return length of string, or -ENOSPC it no space
+ */
-int tis_close(void)
+static int tpm_atmel_twi_get_desc(struct udevice *dev, char *buf, int size)
 {
 	return 0;
 }
 
 /*
- * tis_sendrecv()
+ * tpm_atmel_twi_xfer()
  *
  * Send the requested data to the TPM and then try to get its response
  *
@@ -63,8 +68,9 @@
  * Returns 0 on success (and places the number of response bytes at recv_len)
  * or -1 on failure.
  */
-int tis_sendrecv(const uint8_t *sendbuf, size_t send_size, uint8_t *recvbuf,
-			size_t *recv_len)
+static int tpm_atmel_twi_xfer(struct udevice *dev,
+			      const uint8_t *sendbuf, size_t send_size,
+			      uint8_t *recvbuf, size_t *recv_len)
 {
 	int res;
 	unsigned long start;
@@ -83,6 +89,7 @@
 
 	start = get_timer(0);
 	while ((res = i2c_read(0x29, 0, 0, recvbuf, 10))) {
+		/* TODO Use TIS_TIMEOUT from tpm_tis_infineon.h */
 		if (get_timer(start) > ATMEL_TPM_TIMEOUT_MS) {
 			puts("tpm timed out\n");
 			return -1;
@@ -110,3 +117,28 @@
 
 	return res;
 }
+
+static int tpm_atmel_twi_probe(struct udevice *dev)
+{
+	return 0;
+}
+
+static const struct udevice_id tpm_atmel_twi_ids[] = {
+	{ .compatible = "atmel,at97sc3204t"},
+	{ }
+};
+
+static const struct tpm_ops tpm_atmel_twi_ops = {
+	.open = tpm_atmel_twi_open,
+	.close = tpm_atmel_twi_close,
+	.xfer = tpm_atmel_twi_xfer,
+	.get_desc = tpm_atmel_twi_get_desc,
+};
+
+U_BOOT_DRIVER(tpm_atmel_twi) = {
+	.name = "tpm_atmel_twi",
+	.id = UCLASS_TPM,
+	.of_match = tpm_atmel_twi_ids,
+	.ops = &tpm_atmel_twi_ops,
+	.probe = tpm_atmel_twi_probe,
+};
diff --git a/drivers/tpm/tpm_tis_i2c.c b/drivers/tpm/tpm_tis_infineon.c
similarity index 99%
rename from drivers/tpm/tpm_tis_i2c.c
rename to drivers/tpm/tpm_tis_infineon.c
index 9afe46c..f57c328 100644
--- a/drivers/tpm/tpm_tis_i2c.c
+++ b/drivers/tpm/tpm_tis_infineon.c
@@ -24,14 +24,13 @@
 #include <dm.h>
 #include <fdtdec.h>
 #include <i2c.h>
-#include <tis.h>
 #include <tpm.h>
 #include <asm-generic/errno.h>
 #include <linux/compiler.h>
 #include <linux/types.h>
 #include <linux/unaligned/be_byteshift.h>
 
-#include "tpm_tis_i2c.h"
+#include "tpm_tis_infineon.h"
 #include "tpm_internal.h"
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -614,7 +613,7 @@
 };
 
 U_BOOT_DRIVER(tpm_tis_i2c) = {
-	.name   = "tpm_tis_i2c",
+	.name   = "tpm_tis_infineon",
 	.id     = UCLASS_TPM,
 	.of_match = tpm_tis_i2c_ids,
 	.ops    = &tpm_tis_i2c_ops,
diff --git a/drivers/tpm/tpm_tis_i2c.h b/drivers/tpm/tpm_tis_infineon.h
similarity index 100%
rename from drivers/tpm/tpm_tis_i2c.h
rename to drivers/tpm/tpm_tis_infineon.h
diff --git a/drivers/tpm/tpm_tis_lpc.c b/drivers/tpm/tpm_tis_lpc.c
index b41c3ce..257d035 100644
--- a/drivers/tpm/tpm_tis_lpc.c
+++ b/drivers/tpm/tpm_tis_lpc.c
@@ -16,7 +16,6 @@
 #include <common.h>
 #include <dm.h>
 #include <mapmem.h>
-#include <tis.h>
 #include <tpm.h>
 #include <asm/io.h>
 
diff --git a/drivers/usb/dwc3/linux-compat.h b/drivers/usb/dwc3/linux-compat.h
index b36f68f..6c9c279 100644
--- a/drivers/usb/dwc3/linux-compat.h
+++ b/drivers/usb/dwc3/linux-compat.h
@@ -30,9 +30,4 @@
 {
 	return kzalloc(size, flags);
 }
-
-static inline void *kmalloc_array(size_t n, size_t size, gfp_t flags)
-{
-	return kzalloc(n * size, flags);
-}
 #endif
diff --git a/drivers/usb/eth/smsc95xx.c b/drivers/usb/eth/smsc95xx.c
index e694364..202e482 100644
--- a/drivers/usb/eth/smsc95xx.c
+++ b/drivers/usb/eth/smsc95xx.c
@@ -930,7 +930,7 @@
 #ifdef CONFIG_DM_ETH
 static int smsc95xx_eth_start(struct udevice *dev)
 {
-	struct usb_device *udev = dev_get_parentdata(dev);
+	struct usb_device *udev = dev_get_parent_priv(dev);
 	struct smsc95xx_private *priv = dev_get_priv(dev);
 	struct eth_pdata *pdata = dev_get_platdata(dev);
 
@@ -1014,7 +1014,7 @@
 
 int smsc95xx_write_hwaddr(struct udevice *dev)
 {
-	struct usb_device *udev = dev_get_parentdata(dev);
+	struct usb_device *udev = dev_get_parent_priv(dev);
 	struct eth_pdata *pdata = dev_get_platdata(dev);
 	struct smsc95xx_private *priv = dev_get_priv(dev);
 
diff --git a/drivers/usb/eth/usb_ether.c b/drivers/usb/eth/usb_ether.c
index 3c3e082..62d20f0 100644
--- a/drivers/usb/eth/usb_ether.c
+++ b/drivers/usb/eth/usb_ether.c
@@ -19,7 +19,7 @@
 
 int usb_ether_register(struct udevice *dev, struct ueth_data *ueth, int rxsize)
 {
-	struct usb_device *udev = dev_get_parentdata(dev);
+	struct usb_device *udev = dev_get_parent_priv(dev);
 	struct usb_interface_descriptor *iface_desc;
 	bool ep_in_found = false, ep_out_found = false;
 	struct usb_interface *iface;
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 135ef72..c85dbce 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -303,7 +303,7 @@
 
 	ttdev = udev;
 	parent = udev->dev;
-	uparent = dev_get_parentdata(parent);
+	uparent = dev_get_parent_priv(parent);
 
 	while (uparent->speed != USB_SPEED_HIGH) {
 		struct udevice *dev = parent;
@@ -313,9 +313,9 @@
 			return;
 		}
 
-		ttdev = dev_get_parentdata(dev);
+		ttdev = dev_get_parent_priv(dev);
 		parent = dev->parent;
-		uparent = dev_get_parentdata(parent);
+		uparent = dev_get_parent_priv(parent);
 	}
 	parent_devnum = uparent->devnum;
 #else
diff --git a/drivers/usb/host/usb-uclass.c b/drivers/usb/host/usb-uclass.c
index c66ebb6..7f6a9a6 100644
--- a/drivers/usb/host/usb-uclass.c
+++ b/drivers/usb/host/usb-uclass.c
@@ -289,7 +289,7 @@
 
 	if (!device_active(parent))
 		return NULL;
-	udev = dev_get_parentdata(parent);
+	udev = dev_get_parent_priv(parent);
 	if (udev->devnum == devnum)
 		return udev;
 
@@ -575,7 +575,7 @@
 	udev->portnr = port;
 	debug("Calling usb_setup_device(), portnr=%d\n", udev->portnr);
 	parent_udev = device_get_uclass_id(parent) == UCLASS_USB_HUB ?
-		dev_get_parentdata(parent) : NULL;
+		dev_get_parent_priv(parent) : NULL;
 	ret = usb_setup_device(udev, priv->desc_before_addr, parent_udev);
 	debug("read_descriptor for '%s': ret=%d\n", parent->name, ret);
 	if (ret)
@@ -638,7 +638,7 @@
 			if (!device_active(dev))
 				continue;
 
-			udev = dev_get_parentdata(dev);
+			udev = dev_get_parent_priv(dev);
 			if (usb_get_port_status(udev, udev->portnr, &status)
 					< 0)
 				/* USB request failed */
@@ -694,7 +694,7 @@
 
 int usb_child_pre_probe(struct udevice *dev)
 {
-	struct usb_device *udev = dev_get_parentdata(dev);
+	struct usb_device *udev = dev_get_parent_priv(dev);
 	struct usb_dev_platdata *plat = dev_get_parent_platdata(dev);
 	int ret;
 
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 307e1a6..ca598aa 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -1119,7 +1119,7 @@
 	if (device_get_uclass_id(dev) == UCLASS_USB)
 		udev = dev_get_uclass_priv(dev);
 	else
-		udev = dev_get_parentdata(dev);
+		udev = dev_get_parent_priv(dev);
 
 	return udev;
 }
@@ -1150,7 +1150,7 @@
 		} else {
 			while (!is_root_hub(hub->parent))
 				hub = hub->parent;
-			uhop = dev_get_parentdata(hub);
+			uhop = dev_get_parent_priv(hub);
 			root_portnr = uhop->portnr;
 		}
 	}
diff --git a/drivers/usb/musb-new/usb-compat.h b/drivers/usb/musb-new/usb-compat.h
index 53fe4ff..1c41e2a 100644
--- a/drivers/usb/musb-new/usb-compat.h
+++ b/drivers/usb/musb-new/usb-compat.h
@@ -82,7 +82,7 @@
 	 */
 	ttdev = udev;
 	parent = udev->dev;
-	uparent = dev_get_parentdata(parent);
+	uparent = dev_get_parent_priv(parent);
 
 	while (uparent->speed != USB_SPEED_HIGH) {
 		struct udevice *dev = parent;
@@ -92,9 +92,9 @@
 			return 0;
 		}
 
-		ttdev = dev_get_parentdata(dev);
+		ttdev = dev_get_parent_priv(dev);
 		parent = dev->parent;
-		uparent = dev_get_parentdata(parent);
+		uparent = dev_get_parent_priv(parent);
 	}
 
 	return (uparent->devnum << 8) | (ttdev->portnr - 1);
@@ -119,12 +119,12 @@
 	 * If these 2 are not the same we are being called from
 	 * usb_scan_device() and udev itself is the parent.
 	 */
-	if (dev_get_parentdata(udev->dev) != udev)
+	if (dev_get_parent_priv(udev->dev) != udev)
 		return udev;
 
 	/* We are being called normally, use the parent pointer */
 	if (device_get_uclass_id(parent) == UCLASS_USB_HUB)
-		return dev_get_parentdata(parent);
+		return dev_get_parent_priv(parent);
 
 	return NULL;
 }
diff --git a/fs/ubifs/budget.c b/fs/ubifs/budget.c
index c626cbf..1b4683f 100644
--- a/fs/ubifs/budget.c
+++ b/fs/ubifs/budget.c
@@ -433,7 +433,6 @@
  */
 int ubifs_budget_space(struct ubifs_info *c, struct ubifs_budget_req *req)
 {
-	int uninitialized_var(cmt_retries), uninitialized_var(wb_retries);
 	int err, idx_growth, data_growth, dd_growth, retried = 0;
 
 	ubifs_assert(req->new_page <= 1);
@@ -506,7 +505,7 @@
 			c->bi.nospace_rp = 1;
 		smp_wmb();
 	} else
-		ubifs_err("cannot budget space, error %d", err);
+		ubifs_err(c, "cannot budget space, error %d", err);
 	return err;
 }
 
diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c
index 6e6f018..38c91d0 100644
--- a/fs/ubifs/debug.c
+++ b/fs/ubifs/debug.c
@@ -334,9 +334,9 @@
 		pr_err("\tkey_fmt        %d (%s)\n",
 		       (int)sup->key_fmt, get_key_fmt(sup->key_fmt));
 		pr_err("\tflags          %#x\n", sup_flags);
-		pr_err("\t  big_lpt      %u\n",
+		pr_err("\tbig_lpt        %u\n",
 		       !!(sup_flags & UBIFS_FLG_BIGLPT));
-		pr_err("\t  space_fixup  %u\n",
+		pr_err("\tspace_fixup    %u\n",
 		       !!(sup_flags & UBIFS_FLG_SPACE_FIXUP));
 		pr_err("\tmin_io_size    %u\n", le32_to_cpu(sup->min_io_size));
 		pr_err("\tleb_size       %u\n", le32_to_cpu(sup->leb_size));
@@ -751,8 +751,10 @@
 
 	for (lnum = c->main_first; lnum < c->leb_cnt; lnum++) {
 		err = ubifs_read_one_lp(c, lnum, &lp);
-		if (err)
-			ubifs_err("cannot read lprops for LEB %d", lnum);
+		if (err) {
+			ubifs_err(c, "cannot read lprops for LEB %d", lnum);
+			continue;
+		}
 
 		ubifs_dump_lprop(c, &lp);
 	}
@@ -823,13 +825,13 @@
 
 	buf = __vmalloc(c->leb_size, GFP_NOFS, PAGE_KERNEL);
 	if (!buf) {
-		ubifs_err("cannot allocate memory for dumping LEB %d", lnum);
+		ubifs_err(c, "cannot allocate memory for dumping LEB %d", lnum);
 		return;
 	}
 
 	sleb = ubifs_scan(c, lnum, 0, buf, 0);
 	if (IS_ERR(sleb)) {
-		ubifs_err("scan error %d", (int)PTR_ERR(sleb));
+		ubifs_err(c, "scan error %d", (int)PTR_ERR(sleb));
 		goto out;
 	}
 
@@ -1037,7 +1039,7 @@
 	spin_unlock(&c->space_lock);
 
 	if (free != d->saved_free) {
-		ubifs_err("free space changed from %lld to %lld",
+		ubifs_err(c, "free space changed from %lld to %lld",
 			  d->saved_free, free);
 		goto out;
 	}
@@ -1045,15 +1047,15 @@
 	return 0;
 
 out:
-	ubifs_msg("saved lprops statistics dump");
+	ubifs_msg(c, "saved lprops statistics dump");
 	ubifs_dump_lstats(&d->saved_lst);
-	ubifs_msg("saved budgeting info dump");
+	ubifs_msg(c, "saved budgeting info dump");
 	ubifs_dump_budg(c, &d->saved_bi);
-	ubifs_msg("saved idx_gc_cnt %d", d->saved_idx_gc_cnt);
-	ubifs_msg("current lprops statistics dump");
+	ubifs_msg(c, "saved idx_gc_cnt %d", d->saved_idx_gc_cnt);
+	ubifs_msg(c, "current lprops statistics dump");
 	ubifs_get_lp_stats(c, &lst);
 	ubifs_dump_lstats(&lst);
-	ubifs_msg("current budgeting info dump");
+	ubifs_msg(c, "current budgeting info dump");
 	ubifs_dump_budg(c, &c->bi);
 	dump_stack();
 	return -EINVAL;
@@ -1082,9 +1084,9 @@
 	mutex_lock(&ui->ui_mutex);
 	spin_lock(&ui->ui_lock);
 	if (ui->ui_size != ui->synced_i_size && !ui->dirty) {
-		ubifs_err("ui_size is %lld, synced_i_size is %lld, but inode is clean",
+		ubifs_err(c, "ui_size is %lld, synced_i_size is %lld, but inode is clean",
 			  ui->ui_size, ui->synced_i_size);
-		ubifs_err("i_ino %lu, i_mode %#x, i_size %lld", inode->i_ino,
+		ubifs_err(c, "i_ino %lu, i_mode %#x, i_size %lld", inode->i_ino,
 			  inode->i_mode, i_size_read(inode));
 		dump_stack();
 		err = -EINVAL;
@@ -1145,7 +1147,7 @@
 	kfree(pdent);
 
 	if (i_size_read(dir) != size) {
-		ubifs_err("directory inode %lu has size %llu, but calculated size is %llu",
+		ubifs_err(c, "directory inode %lu has size %llu, but calculated size is %llu",
 			  dir->i_ino, (unsigned long long)i_size_read(dir),
 			  (unsigned long long)size);
 		ubifs_dump_inode(c, dir);
@@ -1153,7 +1155,7 @@
 		return -EINVAL;
 	}
 	if (dir->i_nlink != nlink) {
-		ubifs_err("directory inode %lu has nlink %u, but calculated nlink is %u",
+		ubifs_err(c, "directory inode %lu has nlink %u, but calculated nlink is %u",
 			  dir->i_ino, dir->i_nlink, nlink);
 		ubifs_dump_inode(c, dir);
 		dump_stack();
@@ -1212,10 +1214,10 @@
 	err = 1;
 	key_read(c, &dent1->key, &key);
 	if (keys_cmp(c, &zbr1->key, &key)) {
-		ubifs_err("1st entry at %d:%d has key %s", zbr1->lnum,
+		ubifs_err(c, "1st entry at %d:%d has key %s", zbr1->lnum,
 			  zbr1->offs, dbg_snprintf_key(c, &key, key_buf,
 						       DBG_KEY_BUF_LEN));
-		ubifs_err("but it should have key %s according to tnc",
+		ubifs_err(c, "but it should have key %s according to tnc",
 			  dbg_snprintf_key(c, &zbr1->key, key_buf,
 					   DBG_KEY_BUF_LEN));
 		ubifs_dump_node(c, dent1);
@@ -1224,10 +1226,10 @@
 
 	key_read(c, &dent2->key, &key);
 	if (keys_cmp(c, &zbr2->key, &key)) {
-		ubifs_err("2nd entry at %d:%d has key %s", zbr1->lnum,
+		ubifs_err(c, "2nd entry at %d:%d has key %s", zbr1->lnum,
 			  zbr1->offs, dbg_snprintf_key(c, &key, key_buf,
 						       DBG_KEY_BUF_LEN));
-		ubifs_err("but it should have key %s according to tnc",
+		ubifs_err(c, "but it should have key %s according to tnc",
 			  dbg_snprintf_key(c, &zbr2->key, key_buf,
 					   DBG_KEY_BUF_LEN));
 		ubifs_dump_node(c, dent2);
@@ -1243,14 +1245,14 @@
 		goto out_free;
 	}
 	if (cmp == 0 && nlen1 == nlen2)
-		ubifs_err("2 xent/dent nodes with the same name");
+		ubifs_err(c, "2 xent/dent nodes with the same name");
 	else
-		ubifs_err("bad order of colliding key %s",
+		ubifs_err(c, "bad order of colliding key %s",
 			  dbg_snprintf_key(c, &key, key_buf, DBG_KEY_BUF_LEN));
 
-	ubifs_msg("first node at %d:%d\n", zbr1->lnum, zbr1->offs);
+	ubifs_msg(c, "first node at %d:%d\n", zbr1->lnum, zbr1->offs);
 	ubifs_dump_node(c, dent1);
-	ubifs_msg("second node at %d:%d\n", zbr2->lnum, zbr2->offs);
+	ubifs_msg(c, "second node at %d:%d\n", zbr2->lnum, zbr2->offs);
 	ubifs_dump_node(c, dent2);
 
 out_free:
@@ -1452,11 +1454,11 @@
 	return 0;
 
 out:
-	ubifs_err("failed, error %d", err);
-	ubifs_msg("dump of the znode");
+	ubifs_err(c, "failed, error %d", err);
+	ubifs_msg(c, "dump of the znode");
 	ubifs_dump_znode(c, znode);
 	if (zp) {
-		ubifs_msg("dump of the parent znode");
+		ubifs_msg(c, "dump of the parent znode");
 		ubifs_dump_znode(c, zp);
 	}
 	dump_stack();
@@ -1552,9 +1554,9 @@
 			if (err < 0)
 				return err;
 			if (err) {
-				ubifs_msg("first znode");
+				ubifs_msg(c, "first znode");
 				ubifs_dump_znode(c, prev);
-				ubifs_msg("second znode");
+				ubifs_msg(c, "second znode");
 				ubifs_dump_znode(c, znode);
 				return -EINVAL;
 			}
@@ -1563,13 +1565,13 @@
 
 	if (extra) {
 		if (clean_cnt != atomic_long_read(&c->clean_zn_cnt)) {
-			ubifs_err("incorrect clean_zn_cnt %ld, calculated %ld",
+			ubifs_err(c, "incorrect clean_zn_cnt %ld, calculated %ld",
 				  atomic_long_read(&c->clean_zn_cnt),
 				  clean_cnt);
 			return -EINVAL;
 		}
 		if (dirty_cnt != atomic_long_read(&c->dirty_zn_cnt)) {
-			ubifs_err("incorrect dirty_zn_cnt %ld, calculated %ld",
+			ubifs_err(c, "incorrect dirty_zn_cnt %ld, calculated %ld",
 				  atomic_long_read(&c->dirty_zn_cnt),
 				  dirty_cnt);
 			return -EINVAL;
@@ -1648,7 +1650,7 @@
 		if (znode_cb) {
 			err = znode_cb(c, znode, priv);
 			if (err) {
-				ubifs_err("znode checking function returned error %d",
+				ubifs_err(c, "znode checking function returned error %d",
 					  err);
 				ubifs_dump_znode(c, znode);
 				goto out_dump;
@@ -1659,7 +1661,7 @@
 				zbr = &znode->zbranch[idx];
 				err = leaf_cb(c, zbr, priv);
 				if (err) {
-					ubifs_err("leaf checking function returned error %d, for leaf at LEB %d:%d",
+					ubifs_err(c, "leaf checking function returned error %d, for leaf at LEB %d:%d",
 						  err, zbr->lnum, zbr->offs);
 					goto out_dump;
 				}
@@ -1715,7 +1717,7 @@
 		zbr = &znode->parent->zbranch[znode->iip];
 	else
 		zbr = &c->zroot;
-	ubifs_msg("dump of znode at LEB %d:%d", zbr->lnum, zbr->offs);
+	ubifs_msg(c, "dump of znode at LEB %d:%d", zbr->lnum, zbr->offs);
 	ubifs_dump_znode(c, znode);
 out_unlock:
 	mutex_unlock(&c->tnc_mutex);
@@ -1762,12 +1764,12 @@
 
 	err = dbg_walk_index(c, NULL, add_size, &calc);
 	if (err) {
-		ubifs_err("error %d while walking the index", err);
+		ubifs_err(c, "error %d while walking the index", err);
 		return err;
 	}
 
 	if (calc != idx_size) {
-		ubifs_err("index size check failed: calculated size is %lld, should be %lld",
+		ubifs_err(c, "index size check failed: calculated size is %lld, should be %lld",
 			  calc, idx_size);
 		dump_stack();
 		return -EINVAL;
@@ -1855,7 +1857,7 @@
 	}
 
 	if (inum > c->highest_inum) {
-		ubifs_err("too high inode number, max. is %lu",
+		ubifs_err(c, "too high inode number, max. is %lu",
 			  (unsigned long)c->highest_inum);
 		return ERR_PTR(-EINVAL);
 	}
@@ -1962,17 +1964,17 @@
 	ino_key_init(c, &key, inum);
 	err = ubifs_lookup_level0(c, &key, &znode, &n);
 	if (!err) {
-		ubifs_err("inode %lu not found in index", (unsigned long)inum);
+		ubifs_err(c, "inode %lu not found in index", (unsigned long)inum);
 		return ERR_PTR(-ENOENT);
 	} else if (err < 0) {
-		ubifs_err("error %d while looking up inode %lu",
+		ubifs_err(c, "error %d while looking up inode %lu",
 			  err, (unsigned long)inum);
 		return ERR_PTR(err);
 	}
 
 	zbr = &znode->zbranch[n];
 	if (zbr->len < UBIFS_INO_NODE_SZ) {
-		ubifs_err("bad node %lu node length %d",
+		ubifs_err(c, "bad node %lu node length %d",
 			  (unsigned long)inum, zbr->len);
 		return ERR_PTR(-EINVAL);
 	}
@@ -1983,7 +1985,7 @@
 
 	err = ubifs_tnc_read_node(c, zbr, ino);
 	if (err) {
-		ubifs_err("cannot read inode node at LEB %d:%d, error %d",
+		ubifs_err(c, "cannot read inode node at LEB %d:%d, error %d",
 			  zbr->lnum, zbr->offs, err);
 		kfree(ino);
 		return ERR_PTR(err);
@@ -1992,7 +1994,7 @@
 	fscki = add_inode(c, fsckd, ino);
 	kfree(ino);
 	if (IS_ERR(fscki)) {
-		ubifs_err("error %ld while adding inode %lu node",
+		ubifs_err(c, "error %ld while adding inode %lu node",
 			  PTR_ERR(fscki), (unsigned long)inum);
 		return fscki;
 	}
@@ -2026,7 +2028,7 @@
 	struct fsck_inode *fscki;
 
 	if (zbr->len < UBIFS_CH_SZ) {
-		ubifs_err("bad leaf length %d (LEB %d:%d)",
+		ubifs_err(c, "bad leaf length %d (LEB %d:%d)",
 			  zbr->len, zbr->lnum, zbr->offs);
 		return -EINVAL;
 	}
@@ -2037,7 +2039,7 @@
 
 	err = ubifs_tnc_read_node(c, zbr, node);
 	if (err) {
-		ubifs_err("cannot read leaf node at LEB %d:%d, error %d",
+		ubifs_err(c, "cannot read leaf node at LEB %d:%d, error %d",
 			  zbr->lnum, zbr->offs, err);
 		goto out_free;
 	}
@@ -2047,7 +2049,7 @@
 		fscki = add_inode(c, priv, node);
 		if (IS_ERR(fscki)) {
 			err = PTR_ERR(fscki);
-			ubifs_err("error %d while adding inode node", err);
+			ubifs_err(c, "error %d while adding inode node", err);
 			goto out_dump;
 		}
 		goto out;
@@ -2055,7 +2057,7 @@
 
 	if (type != UBIFS_DENT_KEY && type != UBIFS_XENT_KEY &&
 	    type != UBIFS_DATA_KEY) {
-		ubifs_err("unexpected node type %d at LEB %d:%d",
+		ubifs_err(c, "unexpected node type %d at LEB %d:%d",
 			  type, zbr->lnum, zbr->offs);
 		err = -EINVAL;
 		goto out_free;
@@ -2063,7 +2065,7 @@
 
 	ch = node;
 	if (le64_to_cpu(ch->sqnum) > c->max_sqnum) {
-		ubifs_err("too high sequence number, max. is %llu",
+		ubifs_err(c, "too high sequence number, max. is %llu",
 			  c->max_sqnum);
 		err = -EINVAL;
 		goto out_dump;
@@ -2073,6 +2075,8 @@
 		long long blk_offs;
 		struct ubifs_data_node *dn = node;
 
+		ubifs_assert(zbr->len >= UBIFS_DATA_NODE_SZ);
+
 		/*
 		 * Search the inode node this data node belongs to and insert
 		 * it to the RB-tree of inodes.
@@ -2081,7 +2085,7 @@
 		fscki = read_add_inode(c, priv, inum);
 		if (IS_ERR(fscki)) {
 			err = PTR_ERR(fscki);
-			ubifs_err("error %d while processing data node and trying to find inode node %lu",
+			ubifs_err(c, "error %d while processing data node and trying to find inode node %lu",
 				  err, (unsigned long)inum);
 			goto out_dump;
 		}
@@ -2091,7 +2095,7 @@
 		blk_offs <<= UBIFS_BLOCK_SHIFT;
 		blk_offs += le32_to_cpu(dn->size);
 		if (blk_offs > fscki->size) {
-			ubifs_err("data node at LEB %d:%d is not within inode size %lld",
+			ubifs_err(c, "data node at LEB %d:%d is not within inode size %lld",
 				  zbr->lnum, zbr->offs, fscki->size);
 			err = -EINVAL;
 			goto out_dump;
@@ -2101,6 +2105,8 @@
 		struct ubifs_dent_node *dent = node;
 		struct fsck_inode *fscki1;
 
+		ubifs_assert(zbr->len >= UBIFS_DENT_NODE_SZ);
+
 		err = ubifs_validate_entry(c, dent);
 		if (err)
 			goto out_dump;
@@ -2113,7 +2119,7 @@
 		fscki = read_add_inode(c, priv, inum);
 		if (IS_ERR(fscki)) {
 			err = PTR_ERR(fscki);
-			ubifs_err("error %d while processing entry node and trying to find inode node %lu",
+			ubifs_err(c, "error %d while processing entry node and trying to find inode node %lu",
 				  err, (unsigned long)inum);
 			goto out_dump;
 		}
@@ -2125,7 +2131,7 @@
 		fscki1 = read_add_inode(c, priv, inum);
 		if (IS_ERR(fscki1)) {
 			err = PTR_ERR(fscki1);
-			ubifs_err("error %d while processing entry node and trying to find parent inode node %lu",
+			ubifs_err(c, "error %d while processing entry node and trying to find parent inode node %lu",
 				  err, (unsigned long)inum);
 			goto out_dump;
 		}
@@ -2148,7 +2154,7 @@
 	return 0;
 
 out_dump:
-	ubifs_msg("dump of node at LEB %d:%d", zbr->lnum, zbr->offs);
+	ubifs_msg(c, "dump of node at LEB %d:%d", zbr->lnum, zbr->offs);
 	ubifs_dump_node(c, node);
 out_free:
 	kfree(node);
@@ -2199,52 +2205,52 @@
 			 */
 			if (fscki->inum != UBIFS_ROOT_INO &&
 			    fscki->references != 1) {
-				ubifs_err("directory inode %lu has %d direntries which refer it, but should be 1",
+				ubifs_err(c, "directory inode %lu has %d direntries which refer it, but should be 1",
 					  (unsigned long)fscki->inum,
 					  fscki->references);
 				goto out_dump;
 			}
 			if (fscki->inum == UBIFS_ROOT_INO &&
 			    fscki->references != 0) {
-				ubifs_err("root inode %lu has non-zero (%d) direntries which refer it",
+				ubifs_err(c, "root inode %lu has non-zero (%d) direntries which refer it",
 					  (unsigned long)fscki->inum,
 					  fscki->references);
 				goto out_dump;
 			}
 			if (fscki->calc_sz != fscki->size) {
-				ubifs_err("directory inode %lu size is %lld, but calculated size is %lld",
+				ubifs_err(c, "directory inode %lu size is %lld, but calculated size is %lld",
 					  (unsigned long)fscki->inum,
 					  fscki->size, fscki->calc_sz);
 				goto out_dump;
 			}
 			if (fscki->calc_cnt != fscki->nlink) {
-				ubifs_err("directory inode %lu nlink is %d, but calculated nlink is %d",
+				ubifs_err(c, "directory inode %lu nlink is %d, but calculated nlink is %d",
 					  (unsigned long)fscki->inum,
 					  fscki->nlink, fscki->calc_cnt);
 				goto out_dump;
 			}
 		} else {
 			if (fscki->references != fscki->nlink) {
-				ubifs_err("inode %lu nlink is %d, but calculated nlink is %d",
+				ubifs_err(c, "inode %lu nlink is %d, but calculated nlink is %d",
 					  (unsigned long)fscki->inum,
 					  fscki->nlink, fscki->references);
 				goto out_dump;
 			}
 		}
 		if (fscki->xattr_sz != fscki->calc_xsz) {
-			ubifs_err("inode %lu has xattr size %u, but calculated size is %lld",
+			ubifs_err(c, "inode %lu has xattr size %u, but calculated size is %lld",
 				  (unsigned long)fscki->inum, fscki->xattr_sz,
 				  fscki->calc_xsz);
 			goto out_dump;
 		}
 		if (fscki->xattr_cnt != fscki->calc_xcnt) {
-			ubifs_err("inode %lu has %u xattrs, but calculated count is %lld",
+			ubifs_err(c, "inode %lu has %u xattrs, but calculated count is %lld",
 				  (unsigned long)fscki->inum,
 				  fscki->xattr_cnt, fscki->calc_xcnt);
 			goto out_dump;
 		}
 		if (fscki->xattr_nms != fscki->calc_xnms) {
-			ubifs_err("inode %lu has xattr names' size %u, but calculated names' size is %lld",
+			ubifs_err(c, "inode %lu has xattr names' size %u, but calculated names' size is %lld",
 				  (unsigned long)fscki->inum, fscki->xattr_nms,
 				  fscki->calc_xnms);
 			goto out_dump;
@@ -2258,11 +2264,11 @@
 	ino_key_init(c, &key, fscki->inum);
 	err = ubifs_lookup_level0(c, &key, &znode, &n);
 	if (!err) {
-		ubifs_err("inode %lu not found in index",
+		ubifs_err(c, "inode %lu not found in index",
 			  (unsigned long)fscki->inum);
 		return -ENOENT;
 	} else if (err < 0) {
-		ubifs_err("error %d while looking up inode %lu",
+		ubifs_err(c, "error %d while looking up inode %lu",
 			  err, (unsigned long)fscki->inum);
 		return err;
 	}
@@ -2274,13 +2280,13 @@
 
 	err = ubifs_tnc_read_node(c, zbr, ino);
 	if (err) {
-		ubifs_err("cannot read inode node at LEB %d:%d, error %d",
+		ubifs_err(c, "cannot read inode node at LEB %d:%d, error %d",
 			  zbr->lnum, zbr->offs, err);
 		kfree(ino);
 		return err;
 	}
 
-	ubifs_msg("dump of the inode %lu sitting in LEB %d:%d",
+	ubifs_msg(c, "dump of the inode %lu sitting in LEB %d:%d",
 		  (unsigned long)fscki->inum, zbr->lnum, zbr->offs);
 	ubifs_dump_node(c, ino);
 	kfree(ino);
@@ -2321,7 +2327,7 @@
 	return 0;
 
 out_free:
-	ubifs_err("file-system check failed with error %d", err);
+	ubifs_err(c, "file-system check failed with error %d", err);
 	dump_stack();
 	free_inodes(&fsckd);
 	return err;
@@ -2352,12 +2358,12 @@
 		sb = container_of(cur->next, struct ubifs_scan_node, list);
 
 		if (sa->type != UBIFS_DATA_NODE) {
-			ubifs_err("bad node type %d", sa->type);
+			ubifs_err(c, "bad node type %d", sa->type);
 			ubifs_dump_node(c, sa->node);
 			return -EINVAL;
 		}
 		if (sb->type != UBIFS_DATA_NODE) {
-			ubifs_err("bad node type %d", sb->type);
+			ubifs_err(c, "bad node type %d", sb->type);
 			ubifs_dump_node(c, sb->node);
 			return -EINVAL;
 		}
@@ -2368,7 +2374,7 @@
 		if (inuma < inumb)
 			continue;
 		if (inuma > inumb) {
-			ubifs_err("larger inum %lu goes before inum %lu",
+			ubifs_err(c, "larger inum %lu goes before inum %lu",
 				  (unsigned long)inuma, (unsigned long)inumb);
 			goto error_dump;
 		}
@@ -2377,11 +2383,11 @@
 		blkb = key_block(c, &sb->key);
 
 		if (blka > blkb) {
-			ubifs_err("larger block %u goes before %u", blka, blkb);
+			ubifs_err(c, "larger block %u goes before %u", blka, blkb);
 			goto error_dump;
 		}
 		if (blka == blkb) {
-			ubifs_err("two data nodes for the same block");
+			ubifs_err(c, "two data nodes for the same block");
 			goto error_dump;
 		}
 	}
@@ -2420,19 +2426,19 @@
 
 		if (sa->type != UBIFS_INO_NODE && sa->type != UBIFS_DENT_NODE &&
 		    sa->type != UBIFS_XENT_NODE) {
-			ubifs_err("bad node type %d", sa->type);
+			ubifs_err(c, "bad node type %d", sa->type);
 			ubifs_dump_node(c, sa->node);
 			return -EINVAL;
 		}
 		if (sa->type != UBIFS_INO_NODE && sa->type != UBIFS_DENT_NODE &&
 		    sa->type != UBIFS_XENT_NODE) {
-			ubifs_err("bad node type %d", sb->type);
+			ubifs_err(c, "bad node type %d", sb->type);
 			ubifs_dump_node(c, sb->node);
 			return -EINVAL;
 		}
 
 		if (sa->type != UBIFS_INO_NODE && sb->type == UBIFS_INO_NODE) {
-			ubifs_err("non-inode node goes before inode node");
+			ubifs_err(c, "non-inode node goes before inode node");
 			goto error_dump;
 		}
 
@@ -2442,7 +2448,7 @@
 		if (sa->type == UBIFS_INO_NODE && sb->type == UBIFS_INO_NODE) {
 			/* Inode nodes are sorted in descending size order */
 			if (sa->len < sb->len) {
-				ubifs_err("smaller inode node goes first");
+				ubifs_err(c, "smaller inode node goes first");
 				goto error_dump;
 			}
 			continue;
@@ -2458,7 +2464,7 @@
 		if (inuma < inumb)
 			continue;
 		if (inuma > inumb) {
-			ubifs_err("larger inum %lu goes before inum %lu",
+			ubifs_err(c, "larger inum %lu goes before inum %lu",
 				  (unsigned long)inuma, (unsigned long)inumb);
 			goto error_dump;
 		}
@@ -2467,7 +2473,7 @@
 		hashb = key_block(c, &sb->key);
 
 		if (hasha > hashb) {
-			ubifs_err("larger hash %u goes before %u",
+			ubifs_err(c, "larger hash %u goes before %u",
 				  hasha, hashb);
 			goto error_dump;
 		}
@@ -2476,9 +2482,9 @@
 	return 0;
 
 error_dump:
-	ubifs_msg("dumping first node");
+	ubifs_msg(c, "dumping first node");
 	ubifs_dump_node(c, sa->node);
-	ubifs_msg("dumping second node");
+	ubifs_msg(c, "dumping second node");
 	ubifs_dump_node(c, sb->node);
 	return -EINVAL;
 	return 0;
@@ -2503,17 +2509,17 @@
 
 			if (chance(1, 2)) {
 				d->pc_delay = 1;
-				/* Fail withing 1 minute */
+				/* Fail within 1 minute */
 				delay = prandom_u32() % 60000;
 				d->pc_timeout = jiffies;
 				d->pc_timeout += msecs_to_jiffies(delay);
-				ubifs_warn("failing after %lums", delay);
+				ubifs_warn(c, "failing after %lums", delay);
 			} else {
 				d->pc_delay = 2;
 				delay = prandom_u32() % 10000;
 				/* Fail within 10000 operations */
 				d->pc_cnt_max = delay;
-				ubifs_warn("failing after %lu calls", delay);
+				ubifs_warn(c, "failing after %lu calls", delay);
 			}
 		}
 
@@ -2531,55 +2537,55 @@
 			return 0;
 		if (chance(19, 20))
 			return 0;
-		ubifs_warn("failing in super block LEB %d", lnum);
+		ubifs_warn(c, "failing in super block LEB %d", lnum);
 	} else if (lnum == UBIFS_MST_LNUM || lnum == UBIFS_MST_LNUM + 1) {
 		if (chance(19, 20))
 			return 0;
-		ubifs_warn("failing in master LEB %d", lnum);
+		ubifs_warn(c, "failing in master LEB %d", lnum);
 	} else if (lnum >= UBIFS_LOG_LNUM && lnum <= c->log_last) {
 		if (write && chance(99, 100))
 			return 0;
 		if (chance(399, 400))
 			return 0;
-		ubifs_warn("failing in log LEB %d", lnum);
+		ubifs_warn(c, "failing in log LEB %d", lnum);
 	} else if (lnum >= c->lpt_first && lnum <= c->lpt_last) {
 		if (write && chance(7, 8))
 			return 0;
 		if (chance(19, 20))
 			return 0;
-		ubifs_warn("failing in LPT LEB %d", lnum);
+		ubifs_warn(c, "failing in LPT LEB %d", lnum);
 	} else if (lnum >= c->orph_first && lnum <= c->orph_last) {
 		if (write && chance(1, 2))
 			return 0;
 		if (chance(9, 10))
 			return 0;
-		ubifs_warn("failing in orphan LEB %d", lnum);
+		ubifs_warn(c, "failing in orphan LEB %d", lnum);
 	} else if (lnum == c->ihead_lnum) {
 		if (chance(99, 100))
 			return 0;
-		ubifs_warn("failing in index head LEB %d", lnum);
+		ubifs_warn(c, "failing in index head LEB %d", lnum);
 	} else if (c->jheads && lnum == c->jheads[GCHD].wbuf.lnum) {
 		if (chance(9, 10))
 			return 0;
-		ubifs_warn("failing in GC head LEB %d", lnum);
+		ubifs_warn(c, "failing in GC head LEB %d", lnum);
 	} else if (write && !RB_EMPTY_ROOT(&c->buds) &&
 		   !ubifs_search_bud(c, lnum)) {
 		if (chance(19, 20))
 			return 0;
-		ubifs_warn("failing in non-bud LEB %d", lnum);
+		ubifs_warn(c, "failing in non-bud LEB %d", lnum);
 	} else if (c->cmt_state == COMMIT_RUNNING_BACKGROUND ||
 		   c->cmt_state == COMMIT_RUNNING_REQUIRED) {
 		if (chance(999, 1000))
 			return 0;
-		ubifs_warn("failing in bud LEB %d commit running", lnum);
+		ubifs_warn(c, "failing in bud LEB %d commit running", lnum);
 	} else {
 		if (chance(9999, 10000))
 			return 0;
-		ubifs_warn("failing in bud LEB %d commit not running", lnum);
+		ubifs_warn(c, "failing in bud LEB %d commit not running", lnum);
 	}
 
 	d->pc_happened = 1;
-	ubifs_warn("========== Power cut emulated ==========");
+	ubifs_warn(c, "========== Power cut emulated ==========");
 	dump_stack();
 	return 1;
 }
@@ -2594,7 +2600,7 @@
 	/* Corruption span max to end of write unit */
 	to = min(len, ALIGN(from + 1, c->max_write_size));
 
-	ubifs_warn("filled bytes %u-%u with %s", from, to - 1,
+	ubifs_warn(c, "filled bytes %u-%u with %s", from, to - 1,
 		   ffs ? "0xFFs" : "random data");
 
 	if (ffs)
@@ -2616,7 +2622,7 @@
 	failing = power_cut_emulated(c, lnum, 1);
 	if (failing) {
 		len = corrupt_data(c, buf, len);
-		ubifs_warn("actually write %d bytes to LEB %d:%d (the buffer was corrupted)",
+		ubifs_warn(c, "actually write %d bytes to LEB %d:%d (the buffer was corrupted)",
 			   len, lnum, offs);
 	}
 	err = ubi_leb_write(c->ubi, lnum, buf, offs, len);
@@ -2946,7 +2952,7 @@
 	debugfs_remove_recursive(d->dfs_dir);
 out:
 	err = dent ? PTR_ERR(dent) : -ENODEV;
-	ubifs_err("cannot create \"%s\" debugfs file or directory, error %d\n",
+	ubifs_err(c, "cannot create \"%s\" debugfs file or directory, error %d\n",
 		  fname, err);
 	return err;
 }
@@ -3100,8 +3106,8 @@
 	debugfs_remove_recursive(dfs_rootdir);
 out:
 	err = dent ? PTR_ERR(dent) : -ENODEV;
-	ubifs_err("cannot create \"%s\" debugfs file or directory, error %d\n",
-		  fname, err);
+	pr_err("UBIFS error (pid %d): cannot create \"%s\" debugfs file or directory, error %d\n",
+	       current->pid, fname, err);
 	return err;
 }
 
diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c
index bdccdc4..51a95bb 100644
--- a/fs/ubifs/io.c
+++ b/fs/ubifs/io.c
@@ -79,7 +79,7 @@
 		c->ro_error = 1;
 		c->no_chk_data_crc = 0;
 		c->vfs_sb->s_flags |= MS_RDONLY;
-		ubifs_warn("switched to read-only mode, error %d", err);
+		ubifs_warn(c, "switched to read-only mode, error %d", err);
 		dump_stack();
 	}
 }
@@ -101,7 +101,7 @@
 	 * @even_ebadmsg is true.
 	 */
 	if (err && (err != -EBADMSG || even_ebadmsg)) {
-		ubifs_err("reading %d bytes from LEB %d:%d failed, error %d",
+		ubifs_err(c, "reading %d bytes from LEB %d:%d failed, error %d",
 			  len, lnum, offs, err);
 		dump_stack();
 	}
@@ -118,10 +118,12 @@
 		return -EROFS;
 	if (!dbg_is_tst_rcvry(c))
 		err = ubi_leb_write(c->ubi, lnum, buf, offs, len);
+#ifndef __UBOOT__
 	else
 		err = dbg_leb_write(c, lnum, buf, offs, len);
+#endif
 	if (err) {
-		ubifs_err("writing %d bytes to LEB %d:%d failed, error %d",
+		ubifs_err(c, "writing %d bytes to LEB %d:%d failed, error %d",
 			  len, lnum, offs, err);
 		ubifs_ro_mode(c, err);
 		dump_stack();
@@ -138,10 +140,12 @@
 		return -EROFS;
 	if (!dbg_is_tst_rcvry(c))
 		err = ubi_leb_change(c->ubi, lnum, buf, len);
+#ifndef __UBOOT__
 	else
 		err = dbg_leb_change(c, lnum, buf, len);
+#endif
 	if (err) {
-		ubifs_err("changing %d bytes in LEB %d failed, error %d",
+		ubifs_err(c, "changing %d bytes in LEB %d failed, error %d",
 			  len, lnum, err);
 		ubifs_ro_mode(c, err);
 		dump_stack();
@@ -158,10 +162,12 @@
 		return -EROFS;
 	if (!dbg_is_tst_rcvry(c))
 		err = ubi_leb_unmap(c->ubi, lnum);
+#ifndef __UBOOT__
 	else
 		err = dbg_leb_unmap(c, lnum);
+#endif
 	if (err) {
-		ubifs_err("unmap LEB %d failed, error %d", lnum, err);
+		ubifs_err(c, "unmap LEB %d failed, error %d", lnum, err);
 		ubifs_ro_mode(c, err);
 		dump_stack();
 	}
@@ -177,10 +183,12 @@
 		return -EROFS;
 	if (!dbg_is_tst_rcvry(c))
 		err = ubi_leb_map(c->ubi, lnum);
+#ifndef __UBOOT__
 	else
 		err = dbg_leb_map(c, lnum);
+#endif
 	if (err) {
-		ubifs_err("mapping LEB %d failed, error %d", lnum, err);
+		ubifs_err(c, "mapping LEB %d failed, error %d", lnum, err);
 		ubifs_ro_mode(c, err);
 		dump_stack();
 	}
@@ -193,7 +201,7 @@
 
 	err = ubi_is_mapped(c->ubi, lnum);
 	if (err < 0) {
-		ubifs_err("ubi_is_mapped failed for LEB %d, error %d",
+		ubifs_err(c, "ubi_is_mapped failed for LEB %d, error %d",
 			  lnum, err);
 		dump_stack();
 	}
@@ -241,7 +249,7 @@
 	magic = le32_to_cpu(ch->magic);
 	if (magic != UBIFS_NODE_MAGIC) {
 		if (!quiet)
-			ubifs_err("bad magic %#08x, expected %#08x",
+			ubifs_err(c, "bad magic %#08x, expected %#08x",
 				  magic, UBIFS_NODE_MAGIC);
 		err = -EUCLEAN;
 		goto out;
@@ -250,7 +258,7 @@
 	type = ch->node_type;
 	if (type < 0 || type >= UBIFS_NODE_TYPES_CNT) {
 		if (!quiet)
-			ubifs_err("bad node type %d", type);
+			ubifs_err(c, "bad node type %d", type);
 		goto out;
 	}
 
@@ -273,7 +281,7 @@
 	node_crc = le32_to_cpu(ch->crc);
 	if (crc != node_crc) {
 		if (!quiet)
-			ubifs_err("bad CRC: calculated %#08x, read %#08x",
+			ubifs_err(c, "bad CRC: calculated %#08x, read %#08x",
 				  crc, node_crc);
 		err = -EUCLEAN;
 		goto out;
@@ -283,10 +291,10 @@
 
 out_len:
 	if (!quiet)
-		ubifs_err("bad node length %d", node_len);
+		ubifs_err(c, "bad node length %d", node_len);
 out:
 	if (!quiet) {
-		ubifs_err("bad node at LEB %d:%d", lnum, offs);
+		ubifs_err(c, "bad node at LEB %d:%d", lnum, offs);
 		ubifs_dump_node(c, buf);
 		dump_stack();
 	}
@@ -349,11 +357,11 @@
 
 	if (unlikely(sqnum >= SQNUM_WARN_WATERMARK)) {
 		if (sqnum >= SQNUM_WATERMARK) {
-			ubifs_err("sequence number overflow %llu, end of life",
+			ubifs_err(c, "sequence number overflow %llu, end of life",
 				  sqnum);
 			ubifs_ro_mode(c, -EINVAL);
 		}
-		ubifs_warn("running out of sequence numbers, end of life soon");
+		ubifs_warn(c, "running out of sequence numbers, end of life soon");
 	}
 
 	return sqnum;
@@ -426,7 +434,7 @@
 #ifndef __UBOOT__
 /**
  * wbuf_timer_callback - write-buffer timer callback function.
- * @data: timer data (write-buffer descriptor)
+ * @timer: timer data (write-buffer descriptor)
  *
  * This function is called when the write-buffer timer expires.
  */
@@ -635,7 +643,7 @@
 		err = ubifs_wbuf_sync_nolock(wbuf);
 		mutex_unlock(&wbuf->io_mutex);
 		if (err) {
-			ubifs_err("cannot sync write-buffer, error %d", err);
+			ubifs_err(c, "cannot sync write-buffer, error %d", err);
 			ubifs_ro_mode(c, err);
 			goto out_timers;
 		}
@@ -832,7 +840,7 @@
 	return 0;
 
 out:
-	ubifs_err("cannot write %d bytes to LEB %d:%d, error %d",
+	ubifs_err(c, "cannot write %d bytes to LEB %d:%d, error %d",
 		  len, wbuf->lnum, wbuf->offs, err);
 	ubifs_dump_node(c, buf);
 	dump_stack();
@@ -932,27 +940,27 @@
 	}
 
 	if (type != ch->node_type) {
-		ubifs_err("bad node type (%d but expected %d)",
+		ubifs_err(c, "bad node type (%d but expected %d)",
 			  ch->node_type, type);
 		goto out;
 	}
 
 	err = ubifs_check_node(c, buf, lnum, offs, 0, 0);
 	if (err) {
-		ubifs_err("expected node type %d", type);
+		ubifs_err(c, "expected node type %d", type);
 		return err;
 	}
 
 	rlen = le32_to_cpu(ch->len);
 	if (rlen != len) {
-		ubifs_err("bad node length %d, expected %d", rlen, len);
+		ubifs_err(c, "bad node length %d, expected %d", rlen, len);
 		goto out;
 	}
 
 	return 0;
 
 out:
-	ubifs_err("bad node at LEB %d:%d", lnum, offs);
+	ubifs_err(c, "bad node at LEB %d:%d", lnum, offs);
 	ubifs_dump_node(c, buf);
 	dump_stack();
 	return -EINVAL;
@@ -988,30 +996,32 @@
 		return err;
 
 	if (type != ch->node_type) {
-		ubifs_err("bad node type (%d but expected %d)",
-			  ch->node_type, type);
+		ubifs_errc(c, "bad node type (%d but expected %d)",
+			   ch->node_type, type);
 		goto out;
 	}
 
 	err = ubifs_check_node(c, buf, lnum, offs, 0, 0);
 	if (err) {
-		ubifs_err("expected node type %d", type);
+		ubifs_errc(c, "expected node type %d", type);
 		return err;
 	}
 
 	l = le32_to_cpu(ch->len);
 	if (l != len) {
-		ubifs_err("bad node length %d, expected %d", l, len);
+		ubifs_errc(c, "bad node length %d, expected %d", l, len);
 		goto out;
 	}
 
 	return 0;
 
 out:
-	ubifs_err("bad node at LEB %d:%d, LEB mapping status %d", lnum, offs,
-		  ubi_is_mapped(c->ubi, lnum));
-	ubifs_dump_node(c, buf);
-	dump_stack();
+	ubifs_errc(c, "bad node at LEB %d:%d, LEB mapping status %d", lnum,
+		   offs, ubi_is_mapped(c->ubi, lnum));
+	if (!c->probing) {
+		ubifs_dump_node(c, buf);
+		dump_stack();
+	}
 	return -EINVAL;
 }
 
diff --git a/fs/ubifs/log.c b/fs/ubifs/log.c
index 0355fe2..a07fdef 100644
--- a/fs/ubifs/log.c
+++ b/fs/ubifs/log.c
@@ -98,10 +98,14 @@
 	h = (long long)c->lhead_lnum * c->leb_size + c->lhead_offs;
 	t = (long long)c->ltail_lnum * c->leb_size;
 
-	if (h >= t)
+	if (h > t)
 		return c->log_bytes - h + t;
-	else
+	else if (h != t)
 		return t - h;
+	else if (c->lhead_lnum != c->ltail_lnum)
+		return 0;
+	else
+		return c->log_bytes;
 }
 
 /**
@@ -232,6 +236,7 @@
 
 	if (c->lhead_offs > c->leb_size - c->ref_node_alsz) {
 		c->lhead_lnum = ubifs_next_log_lnum(c, c->lhead_lnum);
+		ubifs_assert(c->lhead_lnum != c->ltail_lnum);
 		c->lhead_offs = 0;
 	}
 
@@ -396,15 +401,14 @@
 	/* Switch to the next log LEB */
 	if (c->lhead_offs) {
 		c->lhead_lnum = ubifs_next_log_lnum(c, c->lhead_lnum);
+		ubifs_assert(c->lhead_lnum != c->ltail_lnum);
 		c->lhead_offs = 0;
 	}
 
-	if (c->lhead_offs == 0) {
-		/* Must ensure next LEB has been unmapped */
-		err = ubifs_leb_unmap(c, c->lhead_lnum);
-		if (err)
-			goto out;
-	}
+	/* Must ensure next LEB has been unmapped */
+	err = ubifs_leb_unmap(c, c->lhead_lnum);
+	if (err)
+		goto out;
 
 	len = ALIGN(len, c->min_io_size);
 	dbg_log("writing commit start at LEB %d:0, len %d", c->lhead_lnum, len);
@@ -439,9 +443,9 @@
  * @ltail_lnum: new log tail LEB number
  *
  * This function is called on when the commit operation was finished. It
- * moves log tail to new position and unmaps LEBs which contain obsolete data.
- * Returns zero in case of success and a negative error code in case of
- * failure.
+ * moves log tail to new position and updates the master node so that it stores
+ * the new log tail LEB number. Returns zero in case of success and a negative
+ * error code in case of failure.
  */
 int ubifs_log_end_commit(struct ubifs_info *c, int ltail_lnum)
 {
@@ -469,7 +473,12 @@
 	spin_unlock(&c->buds_lock);
 
 	err = dbg_check_bud_bytes(c);
+	if (err)
+		goto out;
+
+	err = ubifs_write_master(c);
 
+out:
 	mutex_unlock(&c->log_mutex);
 	return err;
 }
@@ -679,7 +688,7 @@
 	destroy_done_tree(&done_tree);
 	vfree(buf);
 	if (write_lnum == c->lhead_lnum) {
-		ubifs_err("log is too full");
+		ubifs_err(c, "log is too full");
 		return -EINVAL;
 	}
 	/* Unmap remaining LEBs */
@@ -726,7 +735,7 @@
 			bud_bytes += c->leb_size - bud->start;
 
 	if (c->bud_bytes != bud_bytes) {
-		ubifs_err("bad bud_bytes %lld, calculated %lld",
+		ubifs_err(c, "bad bud_bytes %lld, calculated %lld",
 			  c->bud_bytes, bud_bytes);
 		err = -EINVAL;
 	}
diff --git a/fs/ubifs/lprops.c b/fs/ubifs/lprops.c
index a1a814f..292ea7a 100644
--- a/fs/ubifs/lprops.c
+++ b/fs/ubifs/lprops.c
@@ -674,7 +674,7 @@
 out:
 	ubifs_release_lprops(c);
 	if (err)
-		ubifs_err("cannot change properties of LEB %d, error %d",
+		ubifs_err(c, "cannot change properties of LEB %d, error %d",
 			  lnum, err);
 	return err;
 }
@@ -713,7 +713,7 @@
 out:
 	ubifs_release_lprops(c);
 	if (err)
-		ubifs_err("cannot update properties of LEB %d, error %d",
+		ubifs_err(c, "cannot update properties of LEB %d, error %d",
 			  lnum, err);
 	return err;
 }
@@ -738,7 +738,7 @@
 	lpp = ubifs_lpt_lookup(c, lnum);
 	if (IS_ERR(lpp)) {
 		err = PTR_ERR(lpp);
-		ubifs_err("cannot read properties of LEB %d, error %d",
+		ubifs_err(c, "cannot read properties of LEB %d, error %d",
 			  lnum, err);
 		goto out;
 	}
@@ -865,13 +865,13 @@
 
 	list_for_each_entry(lprops, &c->empty_list, list) {
 		if (lprops->free != c->leb_size) {
-			ubifs_err("non-empty LEB %d on empty list (free %d dirty %d flags %d)",
+			ubifs_err(c, "non-empty LEB %d on empty list (free %d dirty %d flags %d)",
 				  lprops->lnum, lprops->free, lprops->dirty,
 				  lprops->flags);
 			return -EINVAL;
 		}
 		if (lprops->flags & LPROPS_TAKEN) {
-			ubifs_err("taken LEB %d on empty list (free %d dirty %d flags %d)",
+			ubifs_err(c, "taken LEB %d on empty list (free %d dirty %d flags %d)",
 				  lprops->lnum, lprops->free, lprops->dirty,
 				  lprops->flags);
 			return -EINVAL;
@@ -881,13 +881,13 @@
 	i = 0;
 	list_for_each_entry(lprops, &c->freeable_list, list) {
 		if (lprops->free + lprops->dirty != c->leb_size) {
-			ubifs_err("non-freeable LEB %d on freeable list (free %d dirty %d flags %d)",
+			ubifs_err(c, "non-freeable LEB %d on freeable list (free %d dirty %d flags %d)",
 				  lprops->lnum, lprops->free, lprops->dirty,
 				  lprops->flags);
 			return -EINVAL;
 		}
 		if (lprops->flags & LPROPS_TAKEN) {
-			ubifs_err("taken LEB %d on freeable list (free %d dirty %d flags %d)",
+			ubifs_err(c, "taken LEB %d on freeable list (free %d dirty %d flags %d)",
 				  lprops->lnum, lprops->free, lprops->dirty,
 				  lprops->flags);
 			return -EINVAL;
@@ -895,7 +895,7 @@
 		i += 1;
 	}
 	if (i != c->freeable_cnt) {
-		ubifs_err("freeable list count %d expected %d", i,
+		ubifs_err(c, "freeable list count %d expected %d", i,
 			  c->freeable_cnt);
 		return -EINVAL;
 	}
@@ -904,26 +904,26 @@
 	list_for_each(pos, &c->idx_gc)
 		i += 1;
 	if (i != c->idx_gc_cnt) {
-		ubifs_err("idx_gc list count %d expected %d", i,
+		ubifs_err(c, "idx_gc list count %d expected %d", i,
 			  c->idx_gc_cnt);
 		return -EINVAL;
 	}
 
 	list_for_each_entry(lprops, &c->frdi_idx_list, list) {
 		if (lprops->free + lprops->dirty != c->leb_size) {
-			ubifs_err("non-freeable LEB %d on frdi_idx list (free %d dirty %d flags %d)",
+			ubifs_err(c, "non-freeable LEB %d on frdi_idx list (free %d dirty %d flags %d)",
 				  lprops->lnum, lprops->free, lprops->dirty,
 				  lprops->flags);
 			return -EINVAL;
 		}
 		if (lprops->flags & LPROPS_TAKEN) {
-			ubifs_err("taken LEB %d on frdi_idx list (free %d dirty %d flags %d)",
+			ubifs_err(c, "taken LEB %d on frdi_idx list (free %d dirty %d flags %d)",
 				  lprops->lnum, lprops->free, lprops->dirty,
 				  lprops->flags);
 			return -EINVAL;
 		}
 		if (!(lprops->flags & LPROPS_INDEX)) {
-			ubifs_err("non-index LEB %d on frdi_idx list (free %d dirty %d flags %d)",
+			ubifs_err(c, "non-index LEB %d on frdi_idx list (free %d dirty %d flags %d)",
 				  lprops->lnum, lprops->free, lprops->dirty,
 				  lprops->flags);
 			return -EINVAL;
@@ -936,15 +936,15 @@
 		for (i = 0; i < heap->cnt; i++) {
 			lprops = heap->arr[i];
 			if (!lprops) {
-				ubifs_err("null ptr in LPT heap cat %d", cat);
+				ubifs_err(c, "null ptr in LPT heap cat %d", cat);
 				return -EINVAL;
 			}
 			if (lprops->hpos != i) {
-				ubifs_err("bad ptr in LPT heap cat %d", cat);
+				ubifs_err(c, "bad ptr in LPT heap cat %d", cat);
 				return -EINVAL;
 			}
 			if (lprops->flags & LPROPS_TAKEN) {
-				ubifs_err("taken LEB in LPT heap cat %d", cat);
+				ubifs_err(c, "taken LEB in LPT heap cat %d", cat);
 				return -EINVAL;
 			}
 		}
@@ -980,7 +980,7 @@
 			goto out;
 		}
 		if (lprops != lp) {
-			ubifs_err("lprops %zx lp %zx lprops->lnum %d lp->lnum %d",
+			ubifs_err(c, "lprops %zx lp %zx lprops->lnum %d lp->lnum %d",
 				  (size_t)lprops, (size_t)lp, lprops->lnum,
 				  lp->lnum);
 			err = 4;
@@ -1000,7 +1000,7 @@
 	}
 out:
 	if (err) {
-		ubifs_err("failed cat %d hpos %d err %d", cat, i, err);
+		ubifs_err(c, "failed cat %d hpos %d err %d", cat, i, err);
 		dump_stack();
 		ubifs_dump_heap(c, heap, cat);
 	}
@@ -1024,14 +1024,14 @@
 {
 	struct ubifs_scan_leb *sleb;
 	struct ubifs_scan_node *snod;
-	int cat, lnum = lp->lnum, is_idx = 0, used = 0, freef, dirty, ret;
+	int cat, lnum = lp->lnum, is_idx = 0, used = 0, free, dirty, ret;
 	void *buf = NULL;
 
 	cat = lp->flags & LPROPS_CAT_MASK;
 	if (cat != LPROPS_UNCAT) {
 		cat = ubifs_categorize_lprops(c, lp);
 		if (cat != (lp->flags & LPROPS_CAT_MASK)) {
-			ubifs_err("bad LEB category %d expected %d",
+			ubifs_err(c, "bad LEB category %d expected %d",
 				  (lp->flags & LPROPS_CAT_MASK), cat);
 			return -EINVAL;
 		}
@@ -1066,7 +1066,7 @@
 				}
 			}
 			if (!found) {
-				ubifs_err("bad LPT list (category %d)", cat);
+				ubifs_err(c, "bad LPT list (category %d)", cat);
 				return -EINVAL;
 			}
 		}
@@ -1078,7 +1078,7 @@
 
 		if ((lp->hpos != -1 && heap->arr[lp->hpos]->lnum != lnum) ||
 		    lp != heap->arr[lp->hpos]) {
-			ubifs_err("bad LPT heap (category %d)", cat);
+			ubifs_err(c, "bad LPT heap (category %d)", cat);
 			return -EINVAL;
 		}
 	}
@@ -1125,7 +1125,7 @@
 			is_idx = (snod->type == UBIFS_IDX_NODE) ? 1 : 0;
 
 		if (is_idx && snod->type != UBIFS_IDX_NODE) {
-			ubifs_err("indexing node in data LEB %d:%d",
+			ubifs_err(c, "indexing node in data LEB %d:%d",
 				  lnum, snod->offs);
 			goto out_destroy;
 		}
@@ -1146,20 +1146,20 @@
 		}
 	}
 
-	freef = c->leb_size - sleb->endpt;
+	free = c->leb_size - sleb->endpt;
 	dirty = sleb->endpt - used;
 
-	if (freef > c->leb_size || freef < 0 || dirty > c->leb_size ||
+	if (free > c->leb_size || free < 0 || dirty > c->leb_size ||
 	    dirty < 0) {
-		ubifs_err("bad calculated accounting for LEB %d: free %d, dirty %d",
-			  lnum, freef, dirty);
+		ubifs_err(c, "bad calculated accounting for LEB %d: free %d, dirty %d",
+			  lnum, free, dirty);
 		goto out_destroy;
 	}
 
 	if (lp->free + lp->dirty == c->leb_size &&
-	    freef + dirty == c->leb_size)
+	    free + dirty == c->leb_size)
 		if ((is_idx && !(lp->flags & LPROPS_INDEX)) ||
-		    (!is_idx && freef == c->leb_size) ||
+		    (!is_idx && free == c->leb_size) ||
 		    lp->free == c->leb_size) {
 			/*
 			 * Empty or freeable LEBs could contain index
@@ -1168,12 +1168,12 @@
 			 * the same reason. Or it may simply not have been
 			 * unmapped.
 			 */
-			freef = lp->free;
+			free = lp->free;
 			dirty = lp->dirty;
 			is_idx = 0;
 		    }
 
-	if (is_idx && lp->free + lp->dirty == freef + dirty &&
+	if (is_idx && lp->free + lp->dirty == free + dirty &&
 	    lnum != c->ihead_lnum) {
 		/*
 		 * After an unclean unmount, an index LEB could have a different
@@ -1186,41 +1186,41 @@
 		 * write to the free space at the end of an index LEB - except
 		 * by the in-the-gaps method for which it is not a problem.
 		 */
-		freef = lp->free;
+		free = lp->free;
 		dirty = lp->dirty;
 	}
 
-	if (lp->free != freef || lp->dirty != dirty)
+	if (lp->free != free || lp->dirty != dirty)
 		goto out_print;
 
 	if (is_idx && !(lp->flags & LPROPS_INDEX)) {
-		if (freef == c->leb_size)
+		if (free == c->leb_size)
 			/* Free but not unmapped LEB, it's fine */
 			is_idx = 0;
 		else {
-			ubifs_err("indexing node without indexing flag");
+			ubifs_err(c, "indexing node without indexing flag");
 			goto out_print;
 		}
 	}
 
 	if (!is_idx && (lp->flags & LPROPS_INDEX)) {
-		ubifs_err("data node with indexing flag");
+		ubifs_err(c, "data node with indexing flag");
 		goto out_print;
 	}
 
-	if (freef == c->leb_size)
+	if (free == c->leb_size)
 		lst->empty_lebs += 1;
 
 	if (is_idx)
 		lst->idx_lebs += 1;
 
 	if (!(lp->flags & LPROPS_INDEX))
-		lst->total_used += c->leb_size - freef - dirty;
-	lst->total_free += freef;
+		lst->total_used += c->leb_size - free - dirty;
+	lst->total_free += free;
 	lst->total_dirty += dirty;
 
 	if (!(lp->flags & LPROPS_INDEX)) {
-		int spc = freef + dirty;
+		int spc = free + dirty;
 
 		if (spc < c->dead_wm)
 			lst->total_dead += spc;
@@ -1233,8 +1233,8 @@
 	return LPT_SCAN_CONTINUE;
 
 out_print:
-	ubifs_err("bad accounting of LEB %d: free %d, dirty %d flags %#x, should be free %d, dirty %d",
-		  lnum, lp->free, lp->dirty, lp->flags, freef, dirty);
+	ubifs_err(c, "bad accounting of LEB %d: free %d, dirty %d flags %#x, should be free %d, dirty %d",
+		  lnum, lp->free, lp->dirty, lp->flags, free, dirty);
 	ubifs_dump_leb(c, lnum);
 out_destroy:
 	ubifs_scan_destroy(sleb);
@@ -1285,11 +1285,11 @@
 	    lst.total_free != c->lst.total_free ||
 	    lst.total_dirty != c->lst.total_dirty ||
 	    lst.total_used != c->lst.total_used) {
-		ubifs_err("bad overall accounting");
-		ubifs_err("calculated: empty_lebs %d, idx_lebs %d, total_free %lld, total_dirty %lld, total_used %lld",
+		ubifs_err(c, "bad overall accounting");
+		ubifs_err(c, "calculated: empty_lebs %d, idx_lebs %d, total_free %lld, total_dirty %lld, total_used %lld",
 			  lst.empty_lebs, lst.idx_lebs, lst.total_free,
 			  lst.total_dirty, lst.total_used);
-		ubifs_err("read from lprops: empty_lebs %d, idx_lebs %d, total_free %lld, total_dirty %lld, total_used %lld",
+		ubifs_err(c, "read from lprops: empty_lebs %d, idx_lebs %d, total_free %lld, total_dirty %lld, total_used %lld",
 			  c->lst.empty_lebs, c->lst.idx_lebs, c->lst.total_free,
 			  c->lst.total_dirty, c->lst.total_used);
 		err = -EINVAL;
@@ -1298,10 +1298,10 @@
 
 	if (lst.total_dead != c->lst.total_dead ||
 	    lst.total_dark != c->lst.total_dark) {
-		ubifs_err("bad dead/dark space accounting");
-		ubifs_err("calculated: total_dead %lld, total_dark %lld",
+		ubifs_err(c, "bad dead/dark space accounting");
+		ubifs_err(c, "calculated: total_dead %lld, total_dark %lld",
 			  lst.total_dead, lst.total_dark);
-		ubifs_err("read from lprops: total_dead %lld, total_dark %lld",
+		ubifs_err(c, "read from lprops: total_dead %lld, total_dark %lld",
 			  c->lst.total_dead, c->lst.total_dark);
 		err = -EINVAL;
 		goto out;
diff --git a/fs/ubifs/lpt.c b/fs/ubifs/lpt.c
index 8489e90..b22b63b 100644
--- a/fs/ubifs/lpt.c
+++ b/fs/ubifs/lpt.c
@@ -141,13 +141,13 @@
 	sz = c->lpt_sz * 2; /* Must have at least 2 times the size */
 	lebs_needed = div_u64(sz + c->leb_size - 1, c->leb_size);
 	if (lebs_needed > c->lpt_lebs) {
-		ubifs_err("too few LPT LEBs");
+		ubifs_err(c, "too few LPT LEBs");
 		return -EINVAL;
 	}
 
 	/* Verify that ltab fits in a single LEB (since ltab is a single node */
 	if (c->ltab_sz > c->leb_size) {
-		ubifs_err("LPT ltab too big");
+		ubifs_err(c, "LPT ltab too big");
 		return -EINVAL;
 	}
 
@@ -209,7 +209,7 @@
 			continue;
 		}
 		if (c->ltab_sz > c->leb_size) {
-			ubifs_err("LPT ltab too big");
+			ubifs_err(c, "LPT ltab too big");
 			return -EINVAL;
 		}
 		*main_lebs = c->main_lebs;
@@ -907,7 +907,7 @@
  *
  * This function returns %0 on success and a negative error code on failure.
  */
-static int check_lpt_crc(void *buf, int len)
+static int check_lpt_crc(const struct ubifs_info *c, void *buf, int len)
 {
 	int pos = 0;
 	uint8_t *addr = buf;
@@ -917,8 +917,8 @@
 	calc_crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES,
 			 len - UBIFS_LPT_CRC_BYTES);
 	if (crc != calc_crc) {
-		ubifs_err("invalid crc in LPT node: crc %hx calc %hx", crc,
-			  calc_crc);
+		ubifs_err(c, "invalid crc in LPT node: crc %hx calc %hx",
+			  crc, calc_crc);
 		dump_stack();
 		return -EINVAL;
 	}
@@ -934,14 +934,15 @@
  *
  * This function returns %0 on success and a negative error code on failure.
  */
-static int check_lpt_type(uint8_t **addr, int *pos, int type)
+static int check_lpt_type(const struct ubifs_info *c, uint8_t **addr,
+			  int *pos, int type)
 {
 	int node_type;
 
 	node_type = ubifs_unpack_bits(addr, pos, UBIFS_LPT_TYPE_BITS);
 	if (node_type != type) {
-		ubifs_err("invalid type (%d) in LPT node type %d", node_type,
-			  type);
+		ubifs_err(c, "invalid type (%d) in LPT node type %d",
+			  node_type, type);
 		dump_stack();
 		return -EINVAL;
 	}
@@ -962,7 +963,7 @@
 	uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
 	int i, pos = 0, err;
 
-	err = check_lpt_type(&addr, &pos, UBIFS_LPT_PNODE);
+	err = check_lpt_type(c, &addr, &pos, UBIFS_LPT_PNODE);
 	if (err)
 		return err;
 	if (c->big_lpt)
@@ -981,7 +982,7 @@
 			lprops->flags = 0;
 		lprops->flags |= ubifs_categorize_lprops(c, lprops);
 	}
-	err = check_lpt_crc(buf, c->pnode_sz);
+	err = check_lpt_crc(c, buf, c->pnode_sz);
 	return err;
 }
 
@@ -999,7 +1000,7 @@
 	uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
 	int i, pos = 0, err;
 
-	err = check_lpt_type(&addr, &pos, UBIFS_LPT_NNODE);
+	err = check_lpt_type(c, &addr, &pos, UBIFS_LPT_NNODE);
 	if (err)
 		return err;
 	if (c->big_lpt)
@@ -1015,7 +1016,7 @@
 		nnode->nbranch[i].offs = ubifs_unpack_bits(&addr, &pos,
 						     c->lpt_offs_bits);
 	}
-	err = check_lpt_crc(buf, c->nnode_sz);
+	err = check_lpt_crc(c, buf, c->nnode_sz);
 	return err;
 }
 
@@ -1031,7 +1032,7 @@
 	uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
 	int i, pos = 0, err;
 
-	err = check_lpt_type(&addr, &pos, UBIFS_LPT_LTAB);
+	err = check_lpt_type(c, &addr, &pos, UBIFS_LPT_LTAB);
 	if (err)
 		return err;
 	for (i = 0; i < c->lpt_lebs; i++) {
@@ -1047,7 +1048,7 @@
 		c->ltab[i].tgc = 0;
 		c->ltab[i].cmt = 0;
 	}
-	err = check_lpt_crc(buf, c->ltab_sz);
+	err = check_lpt_crc(c, buf, c->ltab_sz);
 	return err;
 }
 
@@ -1064,7 +1065,7 @@
 	uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
 	int i, pos = 0, err;
 
-	err = check_lpt_type(&addr, &pos, UBIFS_LPT_LSAVE);
+	err = check_lpt_type(c, &addr, &pos, UBIFS_LPT_LSAVE);
 	if (err)
 		return err;
 	for (i = 0; i < c->lsave_cnt; i++) {
@@ -1074,7 +1075,7 @@
 			return -EINVAL;
 		c->lsave[i] = lnum;
 	}
-	err = check_lpt_crc(buf, c->lsave_sz);
+	err = check_lpt_crc(c, buf, c->lsave_sz);
 	return err;
 }
 #endif
@@ -1241,7 +1242,7 @@
 	return 0;
 
 out:
-	ubifs_err("error %d reading nnode at %d:%d", err, lnum, offs);
+	ubifs_err(c, "error %d reading nnode at %d:%d", err, lnum, offs);
 	dump_stack();
 	kfree(nnode);
 	return err;
@@ -1306,10 +1307,10 @@
 	return 0;
 
 out:
-	ubifs_err("error %d reading pnode at %d:%d", err, lnum, offs);
+	ubifs_err(c, "error %d reading pnode at %d:%d", err, lnum, offs);
 	ubifs_dump_pnode(c, pnode, parent, iip);
 	dump_stack();
-	ubifs_err("calc num: %d", calc_pnode_num_from_parent(c, parent, iip));
+	ubifs_err(c, "calc num: %d", calc_pnode_num_from_parent(c, parent, iip));
 	kfree(pnode);
 	return err;
 }
@@ -1464,7 +1465,6 @@
 			return ERR_CAST(nnode);
 	}
 	iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1));
-	shft -= UBIFS_LPT_FANOUT_SHIFT;
 	pnode = ubifs_get_pnode(c, nnode, iip);
 	if (IS_ERR(pnode))
 		return ERR_CAST(pnode);
@@ -1604,7 +1604,6 @@
 			return ERR_CAST(nnode);
 	}
 	iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1));
-	shft -= UBIFS_LPT_FANOUT_SHIFT;
 	pnode = ubifs_get_pnode(c, nnode, iip);
 	if (IS_ERR(pnode))
 		return ERR_CAST(pnode);
@@ -1970,7 +1969,6 @@
 		}
 	}
 	iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1));
-	shft -= UBIFS_LPT_FANOUT_SHIFT;
 	pnode = scan_get_pnode(c, path + h, nnode, iip);
 	if (IS_ERR(pnode)) {
 		err = PTR_ERR(pnode);
@@ -2104,7 +2102,7 @@
 	int i;
 
 	if (pnode->num != col) {
-		ubifs_err("pnode num %d expected %d parent num %d iip %d",
+		ubifs_err(c, "pnode num %d expected %d parent num %d iip %d",
 			  pnode->num, col, pnode->parent->num, pnode->iip);
 		return -EINVAL;
 	}
@@ -2119,13 +2117,13 @@
 		if (lnum >= c->leb_cnt)
 			continue;
 		if (lprops->lnum != lnum) {
-			ubifs_err("bad LEB number %d expected %d",
+			ubifs_err(c, "bad LEB number %d expected %d",
 				  lprops->lnum, lnum);
 			return -EINVAL;
 		}
 		if (lprops->flags & LPROPS_TAKEN) {
 			if (cat != LPROPS_UNCAT) {
-				ubifs_err("LEB %d taken but not uncat %d",
+				ubifs_err(c, "LEB %d taken but not uncat %d",
 					  lprops->lnum, cat);
 				return -EINVAL;
 			}
@@ -2138,7 +2136,7 @@
 			case LPROPS_FRDI_IDX:
 				break;
 			default:
-				ubifs_err("LEB %d index but cat %d",
+				ubifs_err(c, "LEB %d index but cat %d",
 					  lprops->lnum, cat);
 				return -EINVAL;
 			}
@@ -2151,7 +2149,7 @@
 			case LPROPS_FREEABLE:
 				break;
 			default:
-				ubifs_err("LEB %d not index but cat %d",
+				ubifs_err(c, "LEB %d not index but cat %d",
 					  lprops->lnum, cat);
 				return -EINVAL;
 			}
@@ -2192,26 +2190,28 @@
 			break;
 		}
 		if (!found) {
-			ubifs_err("LEB %d cat %d not found in cat heap/list",
+			ubifs_err(c, "LEB %d cat %d not found in cat heap/list",
 				  lprops->lnum, cat);
 			return -EINVAL;
 		}
 		switch (cat) {
 		case LPROPS_EMPTY:
 			if (lprops->free != c->leb_size) {
-				ubifs_err("LEB %d cat %d free %d dirty %d",
+				ubifs_err(c, "LEB %d cat %d free %d dirty %d",
 					  lprops->lnum, cat, lprops->free,
 					  lprops->dirty);
 				return -EINVAL;
 			}
+			break;
 		case LPROPS_FREEABLE:
 		case LPROPS_FRDI_IDX:
 			if (lprops->free + lprops->dirty != c->leb_size) {
-				ubifs_err("LEB %d cat %d free %d dirty %d",
+				ubifs_err(c, "LEB %d cat %d free %d dirty %d",
 					  lprops->lnum, cat, lprops->free,
 					  lprops->dirty);
 				return -EINVAL;
 			}
+			break;
 		}
 	}
 	return 0;
@@ -2243,7 +2243,7 @@
 			/* cnode is a nnode */
 			num = calc_nnode_num(row, col);
 			if (cnode->num != num) {
-				ubifs_err("nnode num %d expected %d parent num %d iip %d",
+				ubifs_err(c, "nnode num %d expected %d parent num %d iip %d",
 					  cnode->num, num,
 					  (nnode ? nnode->num : 0), cnode->iip);
 				return -EINVAL;
diff --git a/fs/ubifs/lpt_commit.c b/fs/ubifs/lpt_commit.c
index c818d4c..2df9130 100644
--- a/fs/ubifs/lpt_commit.c
+++ b/fs/ubifs/lpt_commit.c
@@ -301,7 +301,6 @@
 			ubifs_assert(lnum >= c->lpt_first &&
 				     lnum <= c->lpt_last);
 		}
-		done_ltab = 1;
 		c->ltab_lnum = lnum;
 		c->ltab_offs = offs;
 		offs += c->ltab_sz;
@@ -317,7 +316,7 @@
 	return 0;
 
 no_space:
-	ubifs_err("LPT out of space at LEB %d:%d needing %d, done_ltab %d, done_lsave %d",
+	ubifs_err(c, "LPT out of space at LEB %d:%d needing %d, done_ltab %d, done_lsave %d",
 		  lnum, offs, len, done_ltab, done_lsave);
 	ubifs_dump_lpt_info(c);
 	ubifs_dump_lpt_lebs(c);
@@ -458,9 +457,9 @@
 		 * important.
 		 */
 		clear_bit(DIRTY_CNODE, &cnode->flags);
-		smp_mb__before_clear_bit();
+		smp_mb__before_atomic();
 		clear_bit(COW_CNODE, &cnode->flags);
-		smp_mb__after_clear_bit();
+		smp_mb__after_atomic();
 		offs += len;
 		dbg_chk_lpt_sz(c, 1, len);
 		cnode = cnode->cnext;
@@ -512,7 +511,6 @@
 			if (err)
 				return err;
 		}
-		done_ltab = 1;
 		ubifs_pack_ltab(c, buf + offs, c->ltab_cmt);
 		offs += c->ltab_sz;
 		dbg_chk_lpt_sz(c, 1, c->ltab_sz);
@@ -543,7 +541,7 @@
 	return 0;
 
 no_space:
-	ubifs_err("LPT out of space mismatch at LEB %d:%d needing %d, done_ltab %d, done_lsave %d",
+	ubifs_err(c, "LPT out of space mismatch at LEB %d:%d needing %d, done_ltab %d, done_lsave %d",
 		  lnum, offs, len, done_ltab, done_lsave);
 	ubifs_dump_lpt_info(c);
 	ubifs_dump_lpt_lebs(c);
@@ -1644,7 +1642,7 @@
 
 	buf = p = __vmalloc(c->leb_size, GFP_NOFS, PAGE_KERNEL);
 	if (!buf) {
-		ubifs_err("cannot allocate memory for ltab checking");
+		ubifs_err(c, "cannot allocate memory for ltab checking");
 		return 0;
 	}
 
@@ -1666,18 +1664,18 @@
 				continue;
 			}
 			if (!dbg_is_all_ff(p, len)) {
-				ubifs_err("invalid empty space in LEB %d at %d",
+				ubifs_err(c, "invalid empty space in LEB %d at %d",
 					  lnum, c->leb_size - len);
 				err = -EINVAL;
 			}
 			i = lnum - c->lpt_first;
 			if (len != c->ltab[i].free) {
-				ubifs_err("invalid free space in LEB %d (free %d, expected %d)",
+				ubifs_err(c, "invalid free space in LEB %d (free %d, expected %d)",
 					  lnum, len, c->ltab[i].free);
 				err = -EINVAL;
 			}
 			if (dirty != c->ltab[i].dirty) {
-				ubifs_err("invalid dirty space in LEB %d (dirty %d, expected %d)",
+				ubifs_err(c, "invalid dirty space in LEB %d (dirty %d, expected %d)",
 					  lnum, dirty, c->ltab[i].dirty);
 				err = -EINVAL;
 			}
@@ -1731,7 +1729,7 @@
 	for (lnum = c->lpt_first; lnum <= c->lpt_last; lnum++) {
 		err = dbg_check_ltab_lnum(c, lnum);
 		if (err) {
-			ubifs_err("failed at LEB %d", lnum);
+			ubifs_err(c, "failed at LEB %d", lnum);
 			return err;
 		}
 	}
@@ -1763,7 +1761,7 @@
 			free += c->leb_size;
 	}
 	if (free < c->lpt_sz) {
-		ubifs_err("LPT space error: free %lld lpt_sz %lld",
+		ubifs_err(c, "LPT space error: free %lld lpt_sz %lld",
 			  free, c->lpt_sz);
 		ubifs_dump_lpt_info(c);
 		ubifs_dump_lpt_lebs(c);
@@ -1803,12 +1801,12 @@
 		d->chk_lpt_lebs = 0;
 		d->chk_lpt_wastage = 0;
 		if (c->dirty_pn_cnt > c->pnode_cnt) {
-			ubifs_err("dirty pnodes %d exceed max %d",
+			ubifs_err(c, "dirty pnodes %d exceed max %d",
 				  c->dirty_pn_cnt, c->pnode_cnt);
 			err = -EINVAL;
 		}
 		if (c->dirty_nn_cnt > c->nnode_cnt) {
-			ubifs_err("dirty nnodes %d exceed max %d",
+			ubifs_err(c, "dirty nnodes %d exceed max %d",
 				  c->dirty_nn_cnt, c->nnode_cnt);
 			err = -EINVAL;
 		}
@@ -1826,22 +1824,22 @@
 		chk_lpt_sz *= d->chk_lpt_lebs;
 		chk_lpt_sz += len - c->nhead_offs;
 		if (d->chk_lpt_sz != chk_lpt_sz) {
-			ubifs_err("LPT wrote %lld but space used was %lld",
+			ubifs_err(c, "LPT wrote %lld but space used was %lld",
 				  d->chk_lpt_sz, chk_lpt_sz);
 			err = -EINVAL;
 		}
 		if (d->chk_lpt_sz > c->lpt_sz) {
-			ubifs_err("LPT wrote %lld but lpt_sz is %lld",
+			ubifs_err(c, "LPT wrote %lld but lpt_sz is %lld",
 				  d->chk_lpt_sz, c->lpt_sz);
 			err = -EINVAL;
 		}
 		if (d->chk_lpt_sz2 && d->chk_lpt_sz != d->chk_lpt_sz2) {
-			ubifs_err("LPT layout size %lld but wrote %lld",
+			ubifs_err(c, "LPT layout size %lld but wrote %lld",
 				  d->chk_lpt_sz, d->chk_lpt_sz2);
 			err = -EINVAL;
 		}
 		if (d->chk_lpt_sz2 && d->new_nhead_offs != len) {
-			ubifs_err("LPT new nhead offs: expected %d was %d",
+			ubifs_err(c, "LPT new nhead offs: expected %d was %d",
 				  d->new_nhead_offs, len);
 			err = -EINVAL;
 		}
@@ -1851,7 +1849,7 @@
 		if (c->big_lpt)
 			lpt_sz += c->lsave_sz;
 		if (d->chk_lpt_sz - d->chk_lpt_wastage > lpt_sz) {
-			ubifs_err("LPT chk_lpt_sz %lld + waste %lld exceeds %lld",
+			ubifs_err(c, "LPT chk_lpt_sz %lld + waste %lld exceeds %lld",
 				  d->chk_lpt_sz, d->chk_lpt_wastage, lpt_sz);
 			err = -EINVAL;
 		}
@@ -1893,7 +1891,7 @@
 	pr_err("(pid %d) start dumping LEB %d\n", current->pid, lnum);
 	buf = p = __vmalloc(c->leb_size, GFP_NOFS, PAGE_KERNEL);
 	if (!buf) {
-		ubifs_err("cannot allocate memory to dump LPT");
+		ubifs_err(c, "cannot allocate memory to dump LPT");
 		return;
 	}
 
@@ -1945,6 +1943,11 @@
 				pr_err("LEB %d:%d, nnode, ",
 				       lnum, offs);
 			err = ubifs_unpack_nnode(c, p, &nnode);
+			if (err) {
+				pr_err("failed to unpack_node, error %d\n",
+				       err);
+				break;
+			}
 			for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
 				pr_cont("%d:%d", nnode.nbranch[i].lnum,
 				       nnode.nbranch[i].offs);
@@ -1963,7 +1966,7 @@
 			pr_err("LEB %d:%d, lsave len\n", lnum, offs);
 			break;
 		default:
-			ubifs_err("LPT node type %d not recognized", node_type);
+			ubifs_err(c, "LPT node type %d not recognized", node_type);
 			goto out;
 		}
 
diff --git a/fs/ubifs/master.c b/fs/ubifs/master.c
index 761e070..4dd0bbb 100644
--- a/fs/ubifs/master.c
+++ b/fs/ubifs/master.c
@@ -76,7 +76,7 @@
 	return -EUCLEAN;
 
 out_dump:
-	ubifs_err("unexpected node type %d master LEB %d:%d",
+	ubifs_err(c, "unexpected node type %d master LEB %d:%d",
 		  snod->type, lnum, snod->offs);
 	ubifs_scan_destroy(sleb);
 	return -EINVAL;
@@ -234,7 +234,7 @@
 	return 0;
 
 out:
-	ubifs_err("bad master node at offset %d error %d", c->mst_offs, err);
+	ubifs_err(c, "bad master node at offset %d error %d", c->mst_offs, err);
 	ubifs_dump_node(c, c->mst_node);
 	return -EINVAL;
 }
@@ -310,7 +310,7 @@
 
 		if (c->leb_cnt < old_leb_cnt ||
 		    c->leb_cnt < UBIFS_MIN_LEB_CNT) {
-			ubifs_err("bad leb_cnt on master node");
+			ubifs_err(c, "bad leb_cnt on master node");
 			ubifs_dump_node(c, c->mst_node);
 			return -EINVAL;
 		}
@@ -349,10 +349,9 @@
  * ubifs_write_master - write master node.
  * @c: UBIFS file-system description object
  *
- * This function writes the master node. The caller has to take the
- * @c->mst_mutex lock before calling this function. Returns zero in case of
- * success and a negative error code in case of failure. The master node is
- * written twice to enable recovery.
+ * This function writes the master node. Returns zero in case of success and a
+ * negative error code in case of failure. The master node is written twice to
+ * enable recovery.
  */
 int ubifs_write_master(struct ubifs_info *c)
 {
diff --git a/fs/ubifs/orphan.c b/fs/ubifs/orphan.c
index 4e42879..f5c8e23 100644
--- a/fs/ubifs/orphan.c
+++ b/fs/ubifs/orphan.c
@@ -78,7 +78,7 @@
 		else if (inum > o->inum)
 			p = &(*p)->rb_right;
 		else {
-			ubifs_err("orphaned twice");
+			ubifs_err(c, "orphaned twice");
 			spin_unlock(&c->orphan_lock);
 			kfree(orphan);
 			return 0;
@@ -145,7 +145,7 @@
 		}
 	}
 	spin_unlock(&c->orphan_lock);
-	ubifs_err("missing orphan ino %lu", (unsigned long)inum);
+	ubifs_err(c, "missing orphan ino %lu", (unsigned long)inum);
 	dump_stack();
 }
 
@@ -277,7 +277,7 @@
 			 * We limit the number of orphans so that this should
 			 * never happen.
 			 */
-			ubifs_err("out of space in orphan area");
+			ubifs_err(c, "out of space in orphan area");
 			return -EINVAL;
 		}
 	}
@@ -336,7 +336,6 @@
 		int lnum;
 
 		/* Unmap any unused LEBs after consolidation */
-		lnum = c->ohead_lnum + 1;
 		for (lnum = c->ohead_lnum + 1; lnum <= c->orph_last; lnum++) {
 			err = ubifs_leb_unmap(c, lnum);
 			if (err)
@@ -388,7 +387,7 @@
 		 * We limit the number of orphans so that this should
 		 * never happen.
 		 */
-		ubifs_err("out of space in orphan area");
+		ubifs_err(c, "out of space in orphan area");
 		err = -EINVAL;
 	}
 	spin_unlock(&c->orphan_lock);
@@ -560,7 +559,7 @@
 
 	list_for_each_entry(snod, &sleb->nodes, list) {
 		if (snod->type != UBIFS_ORPH_NODE) {
-			ubifs_err("invalid node type %d in orphan area at %d:%d",
+			ubifs_err(c, "invalid node type %d in orphan area at %d:%d",
 				  snod->type, sleb->lnum, snod->offs);
 			ubifs_dump_node(c, snod->node);
 			return -EINVAL;
@@ -587,7 +586,7 @@
 			 * number. That makes this orphan node, out of date.
 			 */
 			if (!first) {
-				ubifs_err("out of order commit number %llu in orphan node at %d:%d",
+				ubifs_err(c, "out of order commit number %llu in orphan node at %d:%d",
 					  cmt_no, sleb->lnum, snod->offs);
 				ubifs_dump_node(c, snod->node);
 				return -EINVAL;
@@ -822,20 +821,20 @@
 	if (inum != ci->last_ino) {
 		/* Lowest node type is the inode node, so it comes first */
 		if (key_type(c, &zbr->key) != UBIFS_INO_KEY)
-			ubifs_err("found orphan node ino %lu, type %d",
+			ubifs_err(c, "found orphan node ino %lu, type %d",
 				  (unsigned long)inum, key_type(c, &zbr->key));
 		ci->last_ino = inum;
 		ci->tot_inos += 1;
 		err = ubifs_tnc_read_node(c, zbr, ci->node);
 		if (err) {
-			ubifs_err("node read failed, error %d", err);
+			ubifs_err(c, "node read failed, error %d", err);
 			return err;
 		}
 		if (ci->node->nlink == 0)
 			/* Must be recorded as an orphan */
 			if (!dbg_find_check_orphan(&ci->root, inum) &&
 			    !dbg_find_orphan(c, inum)) {
-				ubifs_err("missing orphan, ino %lu",
+				ubifs_err(c, "missing orphan, ino %lu",
 					  (unsigned long)inum);
 				ci->missing += 1;
 			}
@@ -878,7 +877,7 @@
 
 	buf = __vmalloc(c->leb_size, GFP_NOFS, PAGE_KERNEL);
 	if (!buf) {
-		ubifs_err("cannot allocate memory to check orphans");
+		ubifs_err(c, "cannot allocate memory to check orphans");
 		return 0;
 	}
 
@@ -916,7 +915,7 @@
 	ci.root = RB_ROOT;
 	ci.node = kmalloc(UBIFS_MAX_INO_NODE_SZ, GFP_NOFS);
 	if (!ci.node) {
-		ubifs_err("out of memory");
+		ubifs_err(c, "out of memory");
 		return -ENOMEM;
 	}
 
@@ -926,12 +925,12 @@
 
 	err = dbg_walk_index(c, &dbg_orphan_check, NULL, &ci);
 	if (err) {
-		ubifs_err("cannot scan TNC, error %d", err);
+		ubifs_err(c, "cannot scan TNC, error %d", err);
 		goto out;
 	}
 
 	if (ci.missing) {
-		ubifs_err("%lu missing orphan(s)", ci.missing);
+		ubifs_err(c, "%lu missing orphan(s)", ci.missing);
 		err = -EINVAL;
 		goto out;
 	}
diff --git a/fs/ubifs/recovery.c b/fs/ubifs/recovery.c
index 7637707..386a9c5 100644
--- a/fs/ubifs/recovery.c
+++ b/fs/ubifs/recovery.c
@@ -298,7 +298,7 @@
 		mst = mst2;
 	}
 
-	ubifs_msg("recovered master node from LEB %d",
+	ubifs_msg(c, "recovered master node from LEB %d",
 		  (mst == mst1 ? UBIFS_MST_LNUM : UBIFS_MST_LNUM + 1));
 
 	memcpy(c->mst_node, mst, UBIFS_MST_NODE_SZ);
@@ -355,13 +355,13 @@
 out_err:
 	err = -EINVAL;
 out_free:
-	ubifs_err("failed to recover master node");
+	ubifs_err(c, "failed to recover master node");
 	if (mst1) {
-		ubifs_err("dumping first master node");
+		ubifs_err(c, "dumping first master node");
 		ubifs_dump_node(c, mst1);
 	}
 	if (mst2) {
-		ubifs_err("dumping second master node");
+		ubifs_err(c, "dumping second master node");
 		ubifs_dump_node(c, mst2);
 	}
 	vfree(buf2);
@@ -593,7 +593,6 @@
  * drop_last_node - drop the last node.
  * @sleb: scanned LEB information
  * @offs: offset of dropped nodes is returned here
- * @grouped: non-zero if whole group of nodes have to be dropped
  *
  * This is a helper function for 'ubifs_recover_leb()' which drops the last
  * node of the scanned LEB.
@@ -626,8 +625,8 @@
  *
  * This function does a scan of a LEB, but caters for errors that might have
  * been caused by the unclean unmount from which we are attempting to recover.
- * Returns %0 in case of success, %-EUCLEAN if an unrecoverable corruption is
- * found, and a negative error code in case of failure.
+ * Returns the scanned information on success and a negative error code on
+ * failure.
  */
 struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum,
 					 int offs, void *sbuf, int jhead)
@@ -680,7 +679,7 @@
 				  ret, lnum, offs);
 			break;
 		} else {
-			ubifs_err("unexpected return value %d", ret);
+			ubifs_err(c, "unexpected return value %d", ret);
 			err = -EINVAL;
 			goto error;
 		}
@@ -700,7 +699,7 @@
 			 * See header comment for this file for more
 			 * explanations about the reasons we have this check.
 			 */
-			ubifs_err("corrupt empty space LEB %d:%d, corruption starts at %d",
+			ubifs_err(c, "corrupt empty space LEB %d:%d, corruption starts at %d",
 				  lnum, offs, corruption);
 			/* Make sure we dump interesting non-0xFF data */
 			offs += corruption;
@@ -786,13 +785,13 @@
 
 corrupted_rescan:
 	/* Re-scan the corrupted data with verbose messages */
-	ubifs_err("corruption %d", ret);
+	ubifs_err(c, "corruption %d", ret);
 	ubifs_scan_a_node(c, buf, len, lnum, offs, 1);
 corrupted:
 	ubifs_scanned_corruption(c, lnum, offs, buf);
 	err = -EUCLEAN;
 error:
-	ubifs_err("LEB %d scanning failed", lnum);
+	ubifs_err(c, "LEB %d scanning failed", lnum);
 	ubifs_scan_destroy(sleb);
 	return ERR_PTR(err);
 }
@@ -824,15 +823,15 @@
 		goto out_free;
 	ret = ubifs_scan_a_node(c, cs_node, UBIFS_CS_NODE_SZ, lnum, offs, 0);
 	if (ret != SCANNED_A_NODE) {
-		ubifs_err("Not a valid node");
+		ubifs_err(c, "Not a valid node");
 		goto out_err;
 	}
 	if (cs_node->ch.node_type != UBIFS_CS_NODE) {
-		ubifs_err("Node a CS node, type is %d", cs_node->ch.node_type);
+		ubifs_err(c, "Node a CS node, type is %d", cs_node->ch.node_type);
 		goto out_err;
 	}
 	if (le64_to_cpu(cs_node->cmt_no) != c->cmt_no) {
-		ubifs_err("CS node cmt_no %llu != current cmt_no %llu",
+		ubifs_err(c, "CS node cmt_no %llu != current cmt_no %llu",
 			  (unsigned long long)le64_to_cpu(cs_node->cmt_no),
 			  c->cmt_no);
 		goto out_err;
@@ -845,7 +844,7 @@
 out_err:
 	err = -EINVAL;
 out_free:
-	ubifs_err("failed to get CS sqnum");
+	ubifs_err(c, "failed to get CS sqnum");
 	kfree(cs_node);
 	return err;
 }
@@ -897,7 +896,7 @@
 				}
 			}
 			if (snod->sqnum > cs_sqnum) {
-				ubifs_err("unrecoverable log corruption in LEB %d",
+				ubifs_err(c, "unrecoverable log corruption in LEB %d",
 					  lnum);
 				ubifs_scan_destroy(sleb);
 				return ERR_PTR(-EUCLEAN);
@@ -973,11 +972,8 @@
 		return err;
 
 	dbg_rcvry("checking LPT head at %d:%d", c->nhead_lnum, c->nhead_offs);
-	err = recover_head(c, c->nhead_lnum, c->nhead_offs, sbuf);
-	if (err)
-		return err;
 
-	return 0;
+	return recover_head(c, c->nhead_lnum, c->nhead_offs, sbuf);
 }
 
 /**
@@ -1002,10 +998,7 @@
 
 	if (len == 0) {
 		/* Nothing to read, just unmap it */
-		err = ubifs_leb_unmap(c, lnum);
-		if (err)
-			return err;
-		return 0;
+		return ubifs_leb_unmap(c, lnum);
 	}
 
 	err = ubifs_leb_read(c, lnum, buf, offs, len, 0);
@@ -1041,7 +1034,7 @@
 		}
 
 		if (ret == SCANNED_EMPTY_SPACE) {
-			ubifs_err("unexpected empty space at %d:%d",
+			ubifs_err(c, "unexpected empty space at %d:%d",
 				  lnum, offs);
 			return -EUCLEAN;
 		}
@@ -1136,7 +1129,7 @@
 	 */
 	lnum = ubifs_find_free_leb_for_idx(c);
 	if (lnum < 0) {
-		ubifs_err("could not find an empty LEB");
+		ubifs_err(c, "could not find an empty LEB");
 		ubifs_dump_lprops(c);
 		ubifs_dump_budg(c, &c->bi);
 		return lnum;
@@ -1216,7 +1209,7 @@
 	}
 	mutex_unlock(&wbuf->io_mutex);
 	if (err < 0) {
-		ubifs_err("GC failed, error %d", err);
+		ubifs_err(c, "GC failed, error %d", err);
 		if (err == -EAGAIN)
 			err = -EINVAL;
 		return err;
@@ -1470,7 +1463,7 @@
 	return 0;
 
 out:
-	ubifs_warn("inode %lu failed to fix size %lld -> %lld error %d",
+	ubifs_warn(c, "inode %lu failed to fix size %lld -> %lld error %d",
 		   (unsigned long)e->inum, e->i_size, e->d_size, err);
 	return err;
 }
diff --git a/fs/ubifs/replay.c b/fs/ubifs/replay.c
index 1064cb2..d0fcd83 100644
--- a/fs/ubifs/replay.c
+++ b/fs/ubifs/replay.c
@@ -451,13 +451,13 @@
 	    nlen > UBIFS_MAX_NLEN || dent->name[nlen] != 0 ||
 	    strnlen(dent->name, nlen) != nlen ||
 	    le64_to_cpu(dent->inum) > MAX_INUM) {
-		ubifs_err("bad %s node", key_type == UBIFS_DENT_KEY ?
+		ubifs_err(c, "bad %s node", key_type == UBIFS_DENT_KEY ?
 			  "directory entry" : "extended attribute entry");
 		return -EINVAL;
 	}
 
 	if (key_type != UBIFS_DENT_KEY && key_type != UBIFS_XENT_KEY) {
-		ubifs_err("bad key type %d", key_type);
+		ubifs_err(c, "bad key type %d", key_type);
 		return -EINVAL;
 	}
 
@@ -582,7 +582,7 @@
 		cond_resched();
 
 		if (snod->sqnum >= SQNUM_WATERMARK) {
-			ubifs_err("file system's life ended");
+			ubifs_err(c, "file system's life ended");
 			goto out_dump;
 		}
 
@@ -640,7 +640,7 @@
 			if (old_size < 0 || old_size > c->max_inode_sz ||
 			    new_size < 0 || new_size > c->max_inode_sz ||
 			    old_size <= new_size) {
-				ubifs_err("bad truncation node");
+				ubifs_err(c, "bad truncation node");
 				goto out_dump;
 			}
 
@@ -655,7 +655,7 @@
 			break;
 		}
 		default:
-			ubifs_err("unexpected node type %d in bud LEB %d:%d",
+			ubifs_err(c, "unexpected node type %d in bud LEB %d:%d",
 				  snod->type, lnum, snod->offs);
 			err = -EINVAL;
 			goto out_dump;
@@ -678,7 +678,7 @@
 	return err;
 
 out_dump:
-	ubifs_err("bad node is at LEB %d:%d", lnum, snod->offs);
+	ubifs_err(c, "bad node is at LEB %d:%d", lnum, snod->offs);
 	ubifs_dump_node(c, snod->node);
 	ubifs_scan_destroy(sleb);
 	return -EINVAL;
@@ -798,7 +798,7 @@
 	if (bud) {
 		if (bud->jhead == jhead && bud->start <= offs)
 			return 1;
-		ubifs_err("bud at LEB %d:%d was already referred", lnum, offs);
+		ubifs_err(c, "bud at LEB %d:%d was already referred", lnum, offs);
 		return -EINVAL;
 	}
 
@@ -854,12 +854,12 @@
 		 * numbers.
 		 */
 		if (snod->type != UBIFS_CS_NODE) {
-			ubifs_err("first log node at LEB %d:%d is not CS node",
+			ubifs_err(c, "first log node at LEB %d:%d is not CS node",
 				  lnum, offs);
 			goto out_dump;
 		}
 		if (le64_to_cpu(node->cmt_no) != c->cmt_no) {
-			ubifs_err("first CS node at LEB %d:%d has wrong commit number %llu expected %llu",
+			ubifs_err(c, "first CS node at LEB %d:%d has wrong commit number %llu expected %llu",
 				  lnum, offs,
 				  (unsigned long long)le64_to_cpu(node->cmt_no),
 				  c->cmt_no);
@@ -884,7 +884,7 @@
 
 	/* Make sure the first node sits at offset zero of the LEB */
 	if (snod->offs != 0) {
-		ubifs_err("first node is not at zero offset");
+		ubifs_err(c, "first node is not at zero offset");
 		goto out_dump;
 	}
 
@@ -892,12 +892,12 @@
 		cond_resched();
 
 		if (snod->sqnum >= SQNUM_WATERMARK) {
-			ubifs_err("file system's life ended");
+			ubifs_err(c, "file system's life ended");
 			goto out_dump;
 		}
 
 		if (snod->sqnum < c->cs_sqnum) {
-			ubifs_err("bad sqnum %llu, commit sqnum %llu",
+			ubifs_err(c, "bad sqnum %llu, commit sqnum %llu",
 				  snod->sqnum, c->cs_sqnum);
 			goto out_dump;
 		}
@@ -927,12 +927,12 @@
 		case UBIFS_CS_NODE:
 			/* Make sure it sits at the beginning of LEB */
 			if (snod->offs != 0) {
-				ubifs_err("unexpected node in log");
+				ubifs_err(c, "unexpected node in log");
 				goto out_dump;
 			}
 			break;
 		default:
-			ubifs_err("unexpected node in log");
+			ubifs_err(c, "unexpected node in log");
 			goto out_dump;
 		}
 	}
@@ -948,7 +948,7 @@
 	return err;
 
 out_dump:
-	ubifs_err("log error detected while replaying the log at LEB %d:%d",
+	ubifs_err(c, "log error detected while replaying the log at LEB %d:%d",
 		  lnum, offs + snod->offs);
 	ubifs_dump_node(c, snod->node);
 	ubifs_scan_destroy(sleb);
@@ -1010,7 +1010,7 @@
 		return free; /* Error code */
 
 	if (c->ihead_offs != c->leb_size - free) {
-		ubifs_err("bad index head LEB %d:%d", c->ihead_lnum,
+		ubifs_err(c, "bad index head LEB %d:%d", c->ihead_lnum,
 			  c->ihead_offs);
 		return -EINVAL;
 	}
@@ -1021,9 +1021,22 @@
 
 	do {
 		err = replay_log_leb(c, lnum, 0, c->sbuf);
-		if (err == 1)
-			/* We hit the end of the log */
-			break;
+		if (err == 1) {
+			if (lnum != c->lhead_lnum)
+				/* We hit the end of the log */
+				break;
+
+			/*
+			 * The head of the log must always start with the
+			 * "commit start" node on a properly formatted UBIFS.
+			 * But we found no nodes at all, which means that
+			 * someting went wrong and we cannot proceed mounting
+			 * the file-system.
+			 */
+			ubifs_err(c, "no UBIFS nodes found at the log head LEB %d:%d, possibly corrupted",
+				  lnum, 0);
+			err = -EINVAL;
+		}
 		if (err)
 			goto out;
 		lnum = ubifs_next_log_lnum(c, lnum);
diff --git a/fs/ubifs/sb.c b/fs/ubifs/sb.c
index 4983bf6..7c7d92a 100644
--- a/fs/ubifs/sb.c
+++ b/fs/ubifs/sb.c
@@ -330,8 +330,10 @@
 	cs->ch.node_type = UBIFS_CS_NODE;
 	err = ubifs_write_node(c, cs, UBIFS_CS_NODE_SZ, UBIFS_LOG_LNUM, 0);
 	kfree(cs);
+	if (err)
+		return err;
 
-	ubifs_msg("default file-system created");
+	ubifs_msg(c, "default file-system created");
 	return 0;
 }
 #endif
@@ -362,13 +364,13 @@
 	}
 
 	if (le32_to_cpu(sup->min_io_size) != c->min_io_size) {
-		ubifs_err("min. I/O unit mismatch: %d in superblock, %d real",
+		ubifs_err(c, "min. I/O unit mismatch: %d in superblock, %d real",
 			  le32_to_cpu(sup->min_io_size), c->min_io_size);
 		goto failed;
 	}
 
 	if (le32_to_cpu(sup->leb_size) != c->leb_size) {
-		ubifs_err("LEB size mismatch: %d in superblock, %d real",
+		ubifs_err(c, "LEB size mismatch: %d in superblock, %d real",
 			  le32_to_cpu(sup->leb_size), c->leb_size);
 		goto failed;
 	}
@@ -390,33 +392,33 @@
 	min_leb_cnt += c->lpt_lebs + c->orph_lebs + c->jhead_cnt + 6;
 
 	if (c->leb_cnt < min_leb_cnt || c->leb_cnt > c->vi.size) {
-		ubifs_err("bad LEB count: %d in superblock, %d on UBI volume, %d minimum required",
+		ubifs_err(c, "bad LEB count: %d in superblock, %d on UBI volume, %d minimum required",
 			  c->leb_cnt, c->vi.size, min_leb_cnt);
 		goto failed;
 	}
 
 	if (c->max_leb_cnt < c->leb_cnt) {
-		ubifs_err("max. LEB count %d less than LEB count %d",
+		ubifs_err(c, "max. LEB count %d less than LEB count %d",
 			  c->max_leb_cnt, c->leb_cnt);
 		goto failed;
 	}
 
 	if (c->main_lebs < UBIFS_MIN_MAIN_LEBS) {
-		ubifs_err("too few main LEBs count %d, must be at least %d",
+		ubifs_err(c, "too few main LEBs count %d, must be at least %d",
 			  c->main_lebs, UBIFS_MIN_MAIN_LEBS);
 		goto failed;
 	}
 
 	max_bytes = (long long)c->leb_size * UBIFS_MIN_BUD_LEBS;
 	if (c->max_bud_bytes < max_bytes) {
-		ubifs_err("too small journal (%lld bytes), must be at least %lld bytes",
+		ubifs_err(c, "too small journal (%lld bytes), must be at least %lld bytes",
 			  c->max_bud_bytes, max_bytes);
 		goto failed;
 	}
 
 	max_bytes = (long long)c->leb_size * c->main_lebs;
 	if (c->max_bud_bytes > max_bytes) {
-		ubifs_err("too large journal size (%lld bytes), only %lld bytes available in the main area",
+		ubifs_err(c, "too large journal size (%lld bytes), only %lld bytes available in the main area",
 			  c->max_bud_bytes, max_bytes);
 		goto failed;
 	}
@@ -446,7 +448,7 @@
 		goto failed;
 	}
 
-	if (c->default_compr < 0 || c->default_compr >= UBIFS_COMPR_TYPES_CNT) {
+	if (c->default_compr >= UBIFS_COMPR_TYPES_CNT) {
 		err = 13;
 		goto failed;
 	}
@@ -465,7 +467,7 @@
 	return 0;
 
 failed:
-	ubifs_err("bad superblock, error %d", err);
+	ubifs_err(c, "bad superblock, error %d", err);
 	ubifs_dump_node(c, sup);
 	return -EINVAL;
 }
@@ -551,12 +553,12 @@
 		ubifs_assert(!c->ro_media || c->ro_mount);
 		if (!c->ro_mount ||
 		    c->ro_compat_version > UBIFS_RO_COMPAT_VERSION) {
-			ubifs_err("on-flash format version is w%d/r%d, but software only supports up to version w%d/r%d",
+			ubifs_err(c, "on-flash format version is w%d/r%d, but software only supports up to version w%d/r%d",
 				  c->fmt_version, c->ro_compat_version,
 				  UBIFS_FORMAT_VERSION,
 				  UBIFS_RO_COMPAT_VERSION);
 			if (c->ro_compat_version <= UBIFS_RO_COMPAT_VERSION) {
-				ubifs_msg("only R/O mounting is possible");
+				ubifs_msg(c, "only R/O mounting is possible");
 				err = -EROFS;
 			} else
 				err = -EINVAL;
@@ -572,7 +574,7 @@
 	}
 
 	if (c->fmt_version < 3) {
-		ubifs_err("on-flash format version %d is not supported",
+		ubifs_err(c, "on-flash format version %d is not supported",
 			  c->fmt_version);
 		err = -EINVAL;
 		goto out;
@@ -597,7 +599,7 @@
 		c->key_len = UBIFS_SK_LEN;
 		break;
 	default:
-		ubifs_err("unsupported key format");
+		ubifs_err(c, "unsupported key format");
 		err = -EINVAL;
 		goto out;
 	}
@@ -794,7 +796,7 @@
 	ubifs_assert(c->space_fixup);
 	ubifs_assert(!c->ro_mount);
 
-	ubifs_msg("start fixing up free space");
+	ubifs_msg(c, "start fixing up free space");
 
 	err = fixup_free_space(c);
 	if (err)
@@ -813,6 +815,6 @@
 	if (err)
 		return err;
 
-	ubifs_msg("free space fixup complete");
+	ubifs_msg(c, "free space fixup complete");
 	return err;
 }
diff --git a/fs/ubifs/scan.c b/fs/ubifs/scan.c
index 6fc464b..12a3597 100644
--- a/fs/ubifs/scan.c
+++ b/fs/ubifs/scan.c
@@ -92,7 +92,7 @@
 		if (pad_len < 0 ||
 		    offs + node_len + pad_len > c->leb_size) {
 			if (!quiet) {
-				ubifs_err("bad pad node at LEB %d:%d",
+				ubifs_err(c, "bad pad node at LEB %d:%d",
 					  lnum, offs);
 				ubifs_dump_node(c, pad);
 			}
@@ -102,7 +102,7 @@
 		/* Make the node pads to 8-byte boundary */
 		if ((node_len + pad_len) & 7) {
 			if (!quiet)
-				ubifs_err("bad padding length %d - %d",
+				ubifs_err(c, "bad padding length %d - %d",
 					  offs, offs + node_len + pad_len);
 			return SCANNED_A_BAD_PAD_NODE;
 		}
@@ -123,7 +123,8 @@
  * @offs: offset to start at (usually zero)
  * @sbuf: scan buffer (must be c->leb_size)
  *
- * This function returns %0 on success and a negative error code on failure.
+ * This function returns the scanned information on success and a negative error
+ * code on failure.
  */
 struct ubifs_scan_leb *ubifs_start_scan(const struct ubifs_info *c, int lnum,
 					int offs, void *sbuf)
@@ -143,15 +144,16 @@
 
 	err = ubifs_leb_read(c, lnum, sbuf + offs, offs, c->leb_size - offs, 0);
 	if (err && err != -EBADMSG) {
-		ubifs_err("cannot read %d bytes from LEB %d:%d, error %d",
+		ubifs_err(c, "cannot read %d bytes from LEB %d:%d, error %d",
 			  c->leb_size - offs, lnum, offs, err);
 		kfree(sleb);
 		return ERR_PTR(err);
 	}
 
-	if (err == -EBADMSG)
-		sleb->ecc = 1;
-
+	/*
+	 * Note, we ignore integrity errors (EBASMSG) because all the nodes are
+	 * protected by CRC checksums.
+	 */
 	return sleb;
 }
 
@@ -161,8 +163,6 @@
  * @sleb: scanning information
  * @lnum: logical eraseblock number
  * @offs: offset to start at (usually zero)
- *
- * This function returns %0 on success and a negative error code on failure.
  */
 void ubifs_end_scan(const struct ubifs_info *c, struct ubifs_scan_leb *sleb,
 		    int lnum, int offs)
@@ -232,11 +232,11 @@
 {
 	int len;
 
-	ubifs_err("corruption at LEB %d:%d", lnum, offs);
+	ubifs_err(c, "corruption at LEB %d:%d", lnum, offs);
 	len = c->leb_size - offs;
 	if (len > 8192)
 		len = 8192;
-	ubifs_err("first %d bytes from LEB %d:%d", len, lnum, offs);
+	ubifs_err(c, "first %d bytes from LEB %d:%d", len, lnum, offs);
 	print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 4, buf, len, 1);
 }
 
@@ -249,7 +249,7 @@
  * @quiet: print no messages
  *
  * This function scans LEB number @lnum and returns complete information about
- * its contents. Returns the scaned information in case of success and,
+ * its contents. Returns the scanned information in case of success and,
  * %-EUCLEAN if the LEB neads recovery, and other negative error codes in case
  * of failure.
  *
@@ -291,16 +291,16 @@
 
 		switch (ret) {
 		case SCANNED_GARBAGE:
-			ubifs_err("garbage");
+			ubifs_err(c, "garbage");
 			goto corrupted;
 		case SCANNED_A_NODE:
 			break;
 		case SCANNED_A_CORRUPT_NODE:
 		case SCANNED_A_BAD_PAD_NODE:
-			ubifs_err("bad node");
+			ubifs_err(c, "bad node");
 			goto corrupted;
 		default:
-			ubifs_err("unknown");
+			ubifs_err(c, "unknown");
 			err = -EINVAL;
 			goto error;
 		}
@@ -317,7 +317,7 @@
 
 	if (offs % c->min_io_size) {
 		if (!quiet)
-			ubifs_err("empty space starts at non-aligned offset %d",
+			ubifs_err(c, "empty space starts at non-aligned offset %d",
 				  offs);
 		goto corrupted;
 	}
@@ -330,7 +330,7 @@
 	for (; len; offs++, buf++, len--)
 		if (*(uint8_t *)buf != 0xff) {
 			if (!quiet)
-				ubifs_err("corrupt empty space at LEB %d:%d",
+				ubifs_err(c, "corrupt empty space at LEB %d:%d",
 					  lnum, offs);
 			goto corrupted;
 		}
@@ -340,14 +340,14 @@
 corrupted:
 	if (!quiet) {
 		ubifs_scanned_corruption(c, lnum, offs, buf);
-		ubifs_err("LEB %d scanning failed", lnum);
+		ubifs_err(c, "LEB %d scanning failed", lnum);
 	}
 	err = -EUCLEAN;
 	ubifs_scan_destroy(sleb);
 	return ERR_PTR(err);
 
 error:
-	ubifs_err("LEB %d scanning failed, error %d", lnum, err);
+	ubifs_err(c, "LEB %d scanning failed, error %d", lnum, err);
 	ubifs_scan_destroy(sleb);
 	return ERR_PTR(err);
 }
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index 41763a1..c474313 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -101,7 +101,7 @@
 	}
 
 	if (i >= INODE_LOCKED_MAX) {
-		ubifs_err("Error, can't lock (save) more inodes while recovery!!!");
+		dbg_gen("Error, can't lock (save) more inodes while recovery!!!");
 		return;
 	}
 
@@ -208,13 +208,13 @@
 	const struct ubifs_inode *ui = ubifs_inode(inode);
 
 	if (inode->i_size > c->max_inode_sz) {
-		ubifs_err("inode is too large (%lld)",
+		ubifs_err(c, "inode is too large (%lld)",
 			  (long long)inode->i_size);
 		return 1;
 	}
 
-	if (ui->compr_type < 0 || ui->compr_type >= UBIFS_COMPR_TYPES_CNT) {
-		ubifs_err("unknown compression type %d", ui->compr_type);
+	if (ui->compr_type >= UBIFS_COMPR_TYPES_CNT) {
+		ubifs_err(c, "unknown compression type %d", ui->compr_type);
 		return 2;
 	}
 
@@ -228,7 +228,7 @@
 		return 5;
 
 	if (!ubifs_compr_present(ui->compr_type)) {
-		ubifs_warn("inode %lu uses '%s' compression, but it was not compiled in",
+		ubifs_warn(c, "inode %lu uses '%s' compression, but it was not compiled in",
 			   inode->i_ino, ubifs_compr_name(ui->compr_type));
 	}
 
@@ -321,9 +321,6 @@
 		goto out_invalid;
 
 #ifndef __UBOOT__
-	/* Disable read-ahead */
-	inode->i_mapping->backing_dev_info = &c->bdi;
-
 	switch (inode->i_mode & S_IFMT) {
 	case S_IFREG:
 		inode->i_mapping->a_ops = &ubifs_file_address_operations;
@@ -363,6 +360,7 @@
 		}
 		memcpy(ui->data, ino->data, ui->data_len);
 		((char *)ui->data)[ui->data_len] = '\0';
+		inode->i_link = ui->data;
 		break;
 	case S_IFBLK:
 	case S_IFCHR:
@@ -427,14 +425,14 @@
 	return inode;
 
 out_invalid:
-	ubifs_err("inode %lu validation failed, error %d", inode->i_ino, err);
+	ubifs_err(c, "inode %lu validation failed, error %d", inode->i_ino, err);
 	ubifs_dump_node(c, ino);
 	ubifs_dump_inode(c, inode);
 	err = -EINVAL;
 out_ino:
 	kfree(ino);
 out:
-	ubifs_err("failed to read inode %lu, error %d", inode->i_ino, err);
+	ubifs_err(c, "failed to read inode %lu, error %d", inode->i_ino, err);
 	iget_failed(inode);
 	return ERR_PTR(err);
 }
@@ -505,7 +503,7 @@
 	if (inode->i_nlink) {
 		err = ubifs_jnl_write_inode(c, inode);
 		if (err)
-			ubifs_err("can't write inode %lu, error %d",
+			ubifs_err(c, "can't write inode %lu, error %d",
 				  inode->i_ino, err);
 		else
 			err = dbg_check_inode_size(c, inode, ui->ui_size);
@@ -549,7 +547,7 @@
 		 * Worst case we have a lost orphan inode wasting space, so a
 		 * simple error message is OK here.
 		 */
-		ubifs_err("can't delete inode %lu, error %d",
+		ubifs_err(c, "can't delete inode %lu, error %d",
 			  inode->i_ino, err);
 
 out:
@@ -609,19 +607,19 @@
 	struct ubifs_info *c = root->d_sb->s_fs_info;
 
 	if (c->mount_opts.unmount_mode == 2)
-		seq_printf(s, ",fast_unmount");
+		seq_puts(s, ",fast_unmount");
 	else if (c->mount_opts.unmount_mode == 1)
-		seq_printf(s, ",norm_unmount");
+		seq_puts(s, ",norm_unmount");
 
 	if (c->mount_opts.bulk_read == 2)
-		seq_printf(s, ",bulk_read");
+		seq_puts(s, ",bulk_read");
 	else if (c->mount_opts.bulk_read == 1)
-		seq_printf(s, ",no_bulk_read");
+		seq_puts(s, ",no_bulk_read");
 
 	if (c->mount_opts.chk_data_crc == 2)
-		seq_printf(s, ",chk_data_crc");
+		seq_puts(s, ",chk_data_crc");
 	else if (c->mount_opts.chk_data_crc == 1)
-		seq_printf(s, ",no_chk_data_crc");
+		seq_puts(s, ",no_chk_data_crc");
 
 	if (c->mount_opts.override_compr) {
 		seq_printf(s, ",compr=%s",
@@ -681,17 +679,17 @@
 static int init_constants_early(struct ubifs_info *c)
 {
 	if (c->vi.corrupted) {
-		ubifs_warn("UBI volume is corrupted - read-only mode");
+		ubifs_warn(c, "UBI volume is corrupted - read-only mode");
 		c->ro_media = 1;
 	}
 
 	if (c->di.ro_mode) {
-		ubifs_msg("read-only UBI device");
+		ubifs_msg(c, "read-only UBI device");
 		c->ro_media = 1;
 	}
 
 	if (c->vi.vol_type == UBI_STATIC_VOLUME) {
-		ubifs_msg("static UBI volume - read-only mode");
+		ubifs_msg(c, "static UBI volume - read-only mode");
 		c->ro_media = 1;
 	}
 
@@ -705,19 +703,19 @@
 	c->max_write_shift = fls(c->max_write_size) - 1;
 
 	if (c->leb_size < UBIFS_MIN_LEB_SZ) {
-		ubifs_err("too small LEBs (%d bytes), min. is %d bytes",
+		ubifs_err(c, "too small LEBs (%d bytes), min. is %d bytes",
 			  c->leb_size, UBIFS_MIN_LEB_SZ);
 		return -EINVAL;
 	}
 
 	if (c->leb_cnt < UBIFS_MIN_LEB_CNT) {
-		ubifs_err("too few LEBs (%d), min. is %d",
+		ubifs_err(c, "too few LEBs (%d), min. is %d",
 			  c->leb_cnt, UBIFS_MIN_LEB_CNT);
 		return -EINVAL;
 	}
 
 	if (!is_power_of_2(c->min_io_size)) {
-		ubifs_err("bad min. I/O size %d", c->min_io_size);
+		ubifs_err(c, "bad min. I/O size %d", c->min_io_size);
 		return -EINVAL;
 	}
 
@@ -728,7 +726,7 @@
 	if (c->max_write_size < c->min_io_size ||
 	    c->max_write_size % c->min_io_size ||
 	    !is_power_of_2(c->max_write_size)) {
-		ubifs_err("bad write buffer size %d for %d min. I/O unit",
+		ubifs_err(c, "bad write buffer size %d for %d min. I/O unit",
 			  c->max_write_size, c->min_io_size);
 		return -EINVAL;
 	}
@@ -854,7 +852,7 @@
 	tmp = UBIFS_CS_NODE_SZ + UBIFS_REF_NODE_SZ * c->jhead_cnt;
 	tmp = ALIGN(tmp, c->min_io_size);
 	if (tmp > c->leb_size) {
-		ubifs_err("too small LEB size %d, at least %d needed",
+		ubifs_err(c, "too small LEB size %d, at least %d needed",
 			  c->leb_size, tmp);
 		return -EINVAL;
 	}
@@ -869,7 +867,7 @@
 	tmp /= c->leb_size;
 	tmp += 1;
 	if (c->log_lebs < tmp) {
-		ubifs_err("too small log %d LEBs, required min. %d LEBs",
+		ubifs_err(c, "too small log %d LEBs, required min. %d LEBs",
 			  c->log_lebs, tmp);
 		return -EINVAL;
 	}
@@ -961,7 +959,7 @@
 	int err;
 
 	if (c->gc_lnum == -1) {
-		ubifs_err("no LEB for GC");
+		ubifs_err(c, "no LEB for GC");
 		return -EINVAL;
 	}
 
@@ -982,8 +980,8 @@
 {
 	int i, err;
 
-	c->jheads = kzalloc(c->jhead_cnt * sizeof(struct ubifs_jhead),
-			   GFP_KERNEL);
+	c->jheads = kcalloc(c->jhead_cnt, sizeof(struct ubifs_jhead),
+			    GFP_KERNEL);
 	if (!c->jheads)
 		return -ENOMEM;
 
@@ -1046,7 +1044,7 @@
 		orph = list_entry(c->orph_list.next, struct ubifs_orphan, list);
 		list_del(&orph->list);
 		kfree(orph);
-		ubifs_err("orphan list not empty at unmount");
+		ubifs_err(c, "orphan list not empty at unmount");
 	}
 
 	vfree(c->orph_buf);
@@ -1144,7 +1142,8 @@
  */
 static int parse_standard_option(const char *option)
 {
-	ubifs_msg("parse %s", option);
+
+	pr_notice("UBIFS: parse %s\n", option);
 	if (!strcmp(option, "sync"))
 		return MS_SYNCHRONOUS;
 	return 0;
@@ -1216,7 +1215,7 @@
 			else if (!strcmp(name, "zlib"))
 				c->mount_opts.compr_type = UBIFS_COMPR_ZLIB;
 			else {
-				ubifs_err("unknown compressor \"%s\"", name);
+				ubifs_err(c, "unknown compressor \"%s\"", name); //FIXME: is c ready?
 				kfree(name);
 				return -EINVAL;
 			}
@@ -1232,7 +1231,7 @@
 
 			flag = parse_standard_option(p);
 			if (!flag) {
-				ubifs_err("unrecognized mount option \"%s\" or missing value",
+				ubifs_err(c, "unrecognized mount option \"%s\" or missing value",
 					  p);
 				return -EINVAL;
 			}
@@ -1296,7 +1295,7 @@
 		}
 
 		/* Just disable bulk-read */
-		ubifs_warn("cannot allocate %d bytes of memory for bulk-read, disabling it",
+		ubifs_warn(c, "cannot allocate %d bytes of memory for bulk-read, disabling it",
 			   c->max_bu_buf_len);
 		c->mount_opts.bulk_read = 1;
 		c->bulk_read = 0;
@@ -1316,7 +1315,7 @@
 {
 	ubifs_assert(c->dark_wm > 0);
 	if (c->lst.total_free + c->lst.total_dirty < c->dark_wm) {
-		ubifs_err("insufficient free space to mount in R/W mode");
+		ubifs_err(c, "insufficient free space to mount in R/W mode");
 		ubifs_dump_budg(c, &c->bi);
 		ubifs_dump_lprops(c);
 		return -ENOSPC;
@@ -1339,6 +1338,8 @@
 	size_t sz;
 
 	c->ro_mount = !!(c->vfs_sb->s_flags & MS_RDONLY);
+	/* Suppress error messages while probing if MS_SILENT is set */
+	c->probing = !!(c->vfs_sb->s_flags & MS_SILENT);
 #ifdef __UBOOT__
 	if (!c->ro_mount) {
 		printf("UBIFS: only ro mode in U-Boot allowed.\n");
@@ -1363,14 +1364,14 @@
 		 * This UBI volume is empty, and read-only, or the file system
 		 * is mounted read-only - we cannot format it.
 		 */
-		ubifs_err("can't format empty UBI volume: read-only %s",
+		ubifs_err(c, "can't format empty UBI volume: read-only %s",
 			  c->ro_media ? "UBI volume" : "mount");
 		err = -EROFS;
 		goto out_free;
 	}
 
 	if (c->ro_media && !c->ro_mount) {
-		ubifs_err("cannot mount read-write - read-only media");
+		ubifs_err(c, "cannot mount read-write - read-only media");
 		err = -EROFS;
 		goto out_free;
 	}
@@ -1415,12 +1416,14 @@
 	if (err)
 		goto out_free;
 
+	c->probing = 0;
+
 	/*
 	 * Make sure the compressor which is set as default in the superblock
 	 * or overridden by mount options is actually compiled in.
 	 */
 	if (!ubifs_compr_present(c->default_compr)) {
-		ubifs_err("'compressor \"%s\" is not compiled in",
+		ubifs_err(c, "'compressor \"%s\" is not compiled in",
 			  ubifs_compr_name(c->default_compr));
 		err = -ENOTSUPP;
 		goto out_free;
@@ -1450,7 +1453,7 @@
 		if (IS_ERR(c->bgt)) {
 			err = PTR_ERR(c->bgt);
 			c->bgt = NULL;
-			ubifs_err("cannot spawn \"%s\", error %d",
+			ubifs_err(c, "cannot spawn \"%s\", error %d",
 				  c->bgt_name, err);
 			goto out_wbufs;
 		}
@@ -1465,7 +1468,7 @@
 	init_constants_master(c);
 
 	if ((c->mst_node->flags & cpu_to_le32(UBIFS_MST_DIRTY)) != 0) {
-		ubifs_msg("recovery needed");
+		ubifs_msg(c, "recovery needed");
 		c->need_recovery = 1;
 	}
 
@@ -1488,7 +1491,7 @@
 			goto out_lpt;
 	}
 
-	if (!c->ro_mount) {
+	if (!c->ro_mount && !c->need_recovery) {
 		/*
 		 * Set the "dirty" flag so that if we reboot uncleanly we
 		 * will notice this immediately on the next mount.
@@ -1582,10 +1585,10 @@
 
 	if (c->need_recovery) {
 		if (c->ro_mount)
-			ubifs_msg("recovery deferred");
+			ubifs_msg(c, "recovery deferred");
 		else {
 			c->need_recovery = 0;
-			ubifs_msg("recovery completed");
+			ubifs_msg(c, "recovery completed");
 			/*
 			 * GC LEB has to be empty and taken at this point. But
 			 * the journal head LEBs may also be accounted as
@@ -1606,20 +1609,20 @@
 
 	c->mounting = 0;
 
-	ubifs_msg("mounted UBI device %d, volume %d, name \"%s\"%s",
+	ubifs_msg(c, "UBIFS: mounted UBI device %d, volume %d, name \"%s\"%s",
 		  c->vi.ubi_num, c->vi.vol_id, c->vi.name,
 		  c->ro_mount ? ", R/O mode" : "");
 	x = (long long)c->main_lebs * c->leb_size;
 	y = (long long)c->log_lebs * c->leb_size + c->max_bud_bytes;
-	ubifs_msg("LEB size: %d bytes (%d KiB), min./max. I/O unit sizes: %d bytes/%d bytes",
+	ubifs_msg(c, "LEB size: %d bytes (%d KiB), min./max. I/O unit sizes: %d bytes/%d bytes",
 		  c->leb_size, c->leb_size >> 10, c->min_io_size,
 		  c->max_write_size);
-	ubifs_msg("FS size: %lld bytes (%lld MiB, %d LEBs), journal size %lld bytes (%lld MiB, %d LEBs)",
+	ubifs_msg(c, "FS size: %lld bytes (%lld MiB, %d LEBs), journal size %lld bytes (%lld MiB, %d LEBs)",
 		  x, x >> 20, c->main_lebs,
 		  y, y >> 20, c->log_lebs + c->max_bud_cnt);
-	ubifs_msg("reserved for root: %llu bytes (%llu KiB)",
+	ubifs_msg(c, "reserved for root: %llu bytes (%llu KiB)",
 		  c->report_rp_size, c->report_rp_size >> 10);
-	ubifs_msg("media format: w%d/r%d (latest is w%d/r%d), UUID %pUB%s",
+	ubifs_msg(c, "media format: w%d/r%d (latest is w%d/r%d), UUID %pUB%s",
 		  c->fmt_version, c->ro_compat_version,
 		  UBIFS_FORMAT_VERSION, UBIFS_RO_COMPAT_VERSION, c->uuid,
 		  c->big_lpt ? ", big LPT model" : ", small LPT model");
@@ -1768,8 +1771,8 @@
 	int err, lnum;
 
 	if (c->rw_incompat) {
-		ubifs_err("the file-system is not R/W-compatible");
-		ubifs_msg("on-flash format version is w%d/r%d, but software only supports up to version w%d/r%d",
+		ubifs_err(c, "the file-system is not R/W-compatible");
+		ubifs_msg(c, "on-flash format version is w%d/r%d, but software only supports up to version w%d/r%d",
 			  c->fmt_version, c->ro_compat_version,
 			  UBIFS_FORMAT_VERSION, UBIFS_RO_COMPAT_VERSION);
 		return -EROFS;
@@ -1806,7 +1809,7 @@
 	}
 
 	if (c->need_recovery) {
-		ubifs_msg("completing deferred recovery");
+		ubifs_msg(c, "completing deferred recovery");
 		err = ubifs_write_rcvrd_mst_node(c);
 		if (err)
 			goto out;
@@ -1855,7 +1858,7 @@
 	if (IS_ERR(c->bgt)) {
 		err = PTR_ERR(c->bgt);
 		c->bgt = NULL;
-		ubifs_err("cannot spawn \"%s\", error %d",
+		ubifs_err(c, "cannot spawn \"%s\", error %d",
 			  c->bgt_name, err);
 		goto out;
 	}
@@ -1889,7 +1892,7 @@
 
 	if (c->need_recovery) {
 		c->need_recovery = 0;
-		ubifs_msg("deferred recovery completed");
+		ubifs_msg(c, "deferred recovery completed");
 	} else {
 		/*
 		 * Do not run the debugging space check if the were doing
@@ -1977,8 +1980,7 @@
 	int i;
 	struct ubifs_info *c = sb->s_fs_info;
 
-	ubifs_msg("un-mount UBI device %d, volume %d", c->vi.ubi_num,
-		  c->vi.vol_id);
+	ubifs_msg(c, "un-mount UBI device %d", c->vi.ubi_num);
 
 	/*
 	 * The following asserts are only valid if there has not been a failure
@@ -2034,7 +2036,7 @@
 				 * next mount, so we just print a message and
 				 * continue to unmount normally.
 				 */
-				ubifs_err("failed to write master node, error %d",
+				ubifs_err(c, "failed to write master node, error %d",
 					  err);
 		} else {
 #ifndef __UBOOT__
@@ -2065,17 +2067,17 @@
 
 	err = ubifs_parse_options(c, data, 1);
 	if (err) {
-		ubifs_err("invalid or unknown remount parameter");
+		ubifs_err(c, "invalid or unknown remount parameter");
 		return err;
 	}
 
 	if (c->ro_mount && !(*flags & MS_RDONLY)) {
 		if (c->ro_error) {
-			ubifs_msg("cannot re-mount R/W due to prior errors");
+			ubifs_msg(c, "cannot re-mount R/W due to prior errors");
 			return -EROFS;
 		}
 		if (c->ro_media) {
-			ubifs_msg("cannot re-mount R/W - UBI volume is R/O");
+			ubifs_msg(c, "cannot re-mount R/W - UBI volume is R/O");
 			return -EROFS;
 		}
 		err = ubifs_remount_rw(c);
@@ -2083,7 +2085,7 @@
 			return err;
 	} else if (!c->ro_mount && (*flags & MS_RDONLY)) {
 		if (c->ro_error) {
-			ubifs_msg("cannot re-mount R/O due to prior errors");
+			ubifs_msg(c, "cannot re-mount R/O due to prior errors");
 			return -EROFS;
 		}
 		ubifs_remount_ro(c);
@@ -2200,7 +2202,6 @@
 		mutex_init(&c->lp_mutex);
 		mutex_init(&c->tnc_mutex);
 		mutex_init(&c->log_mutex);
-		mutex_init(&c->mst_mutex);
 		mutex_init(&c->umount_mutex);
 		mutex_init(&c->bu_mutex);
 		mutex_init(&c->write_reserve_mutex);
@@ -2261,8 +2262,8 @@
 	 *
 	 * Read-ahead will be disabled because @c->bdi.ra_pages is 0.
 	 */
-	co>bdi.name = "ubifs",
-	c->bdi.capabilities = BDI_CAP_MAP_COPY;
+	c->bdi.name = "ubifs",
+	c->bdi.capabilities = 0;
 	err  = bdi_init(&c->bdi);
 	if (err)
 		goto out_close;
@@ -2285,6 +2286,9 @@
 	if (c->max_inode_sz > MAX_LFS_FILESIZE)
 		sb->s_maxbytes = c->max_inode_sz = MAX_LFS_FILESIZE;
 	sb->s_op = &ubifs_super_operations;
+#ifndef __UBOOT__
+	sb->s_xattr = ubifs_xattr_handlers;
+#endif
 
 	mutex_lock(&c->umount_mutex);
 	err = mount_ubifs(c);
@@ -2453,8 +2457,8 @@
 	 */
 	ubi = open_ubi(name, UBI_READONLY);
 	if (IS_ERR(ubi)) {
-		ubifs_err("cannot open \"%s\", error %d",
-			  name, (int)PTR_ERR(ubi));
+		pr_err("UBIFS error (pid: %d): cannot open \"%s\", error %d",
+		       current->pid, name, (int)PTR_ERR(ubi));
 		return ERR_CAST(ubi);
 	}
 
@@ -2595,8 +2599,8 @@
 	 * UBIFS_BLOCK_SIZE. It is assumed that both are powers of 2.
 	 */
 	if (PAGE_CACHE_SIZE < UBIFS_BLOCK_SIZE) {
-		ubifs_err("VFS page cache size is %u bytes, but UBIFS requires at least 4096 bytes",
-			  (unsigned int)PAGE_CACHE_SIZE);
+		pr_err("UBIFS error (pid %d): VFS page cache size is %u bytes, but UBIFS requires at least 4096 bytes",
+		       current->pid, (unsigned int)PAGE_CACHE_SIZE);
 		return -EINVAL;
 	}
 
@@ -2608,7 +2612,9 @@
 	if (!ubifs_inode_slab)
 		return -ENOMEM;
 
-	register_shrinker(&ubifs_shrinker_info);
+	err = register_shrinker(&ubifs_shrinker_info);
+	if (err)
+		goto out_slab;
 #endif
 
 	err = ubifs_compressors_init();
@@ -2622,7 +2628,8 @@
 
 	err = register_filesystem(&ubifs_fs_type);
 	if (err) {
-		ubifs_err("cannot register file system, error %d", err);
+		pr_err("UBIFS error (pid %d): cannot register file system, error %d",
+		       current->pid, err);
 		goto out_dbg;
 	}
 #endif
@@ -2637,6 +2644,7 @@
 out_shrinker:
 #ifndef __UBOOT__
 	unregister_shrinker(&ubifs_shrinker_info);
+out_slab:
 #endif
 	kmem_cache_destroy(ubifs_inode_slab);
 	return err;
diff --git a/fs/ubifs/tnc.c b/fs/ubifs/tnc.c
index e20cedd..f6316a3 100644
--- a/fs/ubifs/tnc.c
+++ b/fs/ubifs/tnc.c
@@ -93,7 +93,7 @@
 		else if (offs > o->offs)
 			p = &(*p)->rb_right;
 		else {
-			ubifs_err("old idx added twice!");
+			ubifs_err(c, "old idx added twice!");
 			kfree(old_idx);
 			return 0;
 		}
@@ -442,7 +442,7 @@
 
 	err = ubifs_leb_read(c, lnum, buf, offs, len, 1);
 	if (err) {
-		ubifs_err("cannot read node type %d from LEB %d:%d, error %d",
+		ubifs_err(c, "cannot read node type %d from LEB %d:%d, error %d",
 			  type, lnum, offs, err);
 		return err;
 	}
@@ -1683,27 +1683,27 @@
 	int err, len;
 
 	if (ch->node_type != UBIFS_DATA_NODE) {
-		ubifs_err("bad node type (%d but expected %d)",
+		ubifs_err(c, "bad node type (%d but expected %d)",
 			  ch->node_type, UBIFS_DATA_NODE);
 		goto out_err;
 	}
 
 	err = ubifs_check_node(c, buf, zbr->lnum, zbr->offs, 0, 0);
 	if (err) {
-		ubifs_err("expected node type %d", UBIFS_DATA_NODE);
+		ubifs_err(c, "expected node type %d", UBIFS_DATA_NODE);
 		goto out;
 	}
 
 	len = le32_to_cpu(ch->len);
 	if (len != zbr->len) {
-		ubifs_err("bad node length %d, expected %d", len, zbr->len);
+		ubifs_err(c, "bad node length %d, expected %d", len, zbr->len);
 		goto out_err;
 	}
 
 	/* Make sure the key of the read node is correct */
 	key_read(c, buf + UBIFS_KEY_OFFSET, &key1);
 	if (!keys_eq(c, &zbr->key, &key1)) {
-		ubifs_err("bad key in node at LEB %d:%d",
+		ubifs_err(c, "bad key in node at LEB %d:%d",
 			  zbr->lnum, zbr->offs);
 		dbg_tnck(&zbr->key, "looked for key ");
 		dbg_tnck(&key1, "found node's key ");
@@ -1715,7 +1715,7 @@
 out_err:
 	err = -EINVAL;
 out:
-	ubifs_err("bad node at LEB %d:%d", zbr->lnum, zbr->offs);
+	ubifs_err(c, "bad node at LEB %d:%d", zbr->lnum, zbr->offs);
 	ubifs_dump_node(c, buf);
 	dump_stack();
 	return err;
@@ -1740,7 +1740,7 @@
 	len = bu->zbranch[bu->cnt - 1].offs;
 	len += bu->zbranch[bu->cnt - 1].len - offs;
 	if (len > bu->buf_len) {
-		ubifs_err("buffer too small %d vs %d", bu->buf_len, len);
+		ubifs_err(c, "buffer too small %d vs %d", bu->buf_len, len);
 		return -EINVAL;
 	}
 
@@ -1756,7 +1756,7 @@
 		return -EAGAIN;
 
 	if (err && err != -EBADMSG) {
-		ubifs_err("failed to read from LEB %d:%d, error %d",
+		ubifs_err(c, "failed to read from LEB %d:%d, error %d",
 			  lnum, offs, err);
 		dump_stack();
 		dbg_tnck(&bu->key, "key ");
@@ -2858,10 +2858,11 @@
 {
 	tnc_destroy_cnext(c);
 	if (c->zroot.znode) {
-		long n;
+		long n, freed;
 
-		ubifs_destroy_tnc_subtree(c->zroot.znode);
 		n = atomic_long_read(&c->clean_zn_cnt);
+		freed = ubifs_destroy_tnc_subtree(c->zroot.znode);
+		ubifs_assert(freed == n);
 		atomic_long_sub(n, &ubifs_clean_zn_cnt);
 	}
 	kfree(c->gap_lebs);
@@ -3292,7 +3293,6 @@
 		goto out_unlock;
 
 	if (err) {
-		err = -EINVAL;
 		key = &from_key;
 		goto out_dump;
 	}
@@ -3312,7 +3312,7 @@
 
 out_dump:
 	block = key_block(c, key);
-	ubifs_err("inode %lu has size %lld, but there are data at offset %lld",
+	ubifs_err(c, "inode %lu has size %lld, but there are data at offset %lld",
 		  (unsigned long)inode->i_ino, size,
 		  ((loff_t)block) << UBIFS_BLOCK_SHIFT);
 	mutex_unlock(&c->tnc_mutex);
diff --git a/fs/ubifs/tnc_misc.c b/fs/ubifs/tnc_misc.c
index f808e0b..b1bb647 100644
--- a/fs/ubifs/tnc_misc.c
+++ b/fs/ubifs/tnc_misc.c
@@ -285,9 +285,9 @@
 		lnum, offs, znode->level, znode->child_cnt);
 
 	if (znode->child_cnt > c->fanout || znode->level > UBIFS_MAX_LEVELS) {
-		ubifs_err("current fanout %d, branch count %d",
+		ubifs_err(c, "current fanout %d, branch count %d",
 			  c->fanout, znode->child_cnt);
-		ubifs_err("max levels %d, znode level %d",
+		ubifs_err(c, "max levels %d, znode level %d",
 			  UBIFS_MAX_LEVELS, znode->level);
 		err = 1;
 		goto out_dump;
@@ -308,7 +308,7 @@
 		if (zbr->lnum < c->main_first ||
 		    zbr->lnum >= c->leb_cnt || zbr->offs < 0 ||
 		    zbr->offs + zbr->len > c->leb_size || zbr->offs & 7) {
-			ubifs_err("bad branch %d", i);
+			ubifs_err(c, "bad branch %d", i);
 			err = 2;
 			goto out_dump;
 		}
@@ -320,7 +320,7 @@
 		case UBIFS_XENT_KEY:
 			break;
 		default:
-			ubifs_err("bad key type at slot %d: %d",
+			ubifs_err(c, "bad key type at slot %d: %d",
 				  i, key_type(c, &zbr->key));
 			err = 3;
 			goto out_dump;
@@ -332,17 +332,17 @@
 		type = key_type(c, &zbr->key);
 		if (c->ranges[type].max_len == 0) {
 			if (zbr->len != c->ranges[type].len) {
-				ubifs_err("bad target node (type %d) length (%d)",
+				ubifs_err(c, "bad target node (type %d) length (%d)",
 					  type, zbr->len);
-				ubifs_err("have to be %d", c->ranges[type].len);
+				ubifs_err(c, "have to be %d", c->ranges[type].len);
 				err = 4;
 				goto out_dump;
 			}
 		} else if (zbr->len < c->ranges[type].min_len ||
 			   zbr->len > c->ranges[type].max_len) {
-			ubifs_err("bad target node (type %d) length (%d)",
+			ubifs_err(c, "bad target node (type %d) length (%d)",
 				  type, zbr->len);
-			ubifs_err("have to be in range of %d-%d",
+			ubifs_err(c, "have to be in range of %d-%d",
 				  c->ranges[type].min_len,
 				  c->ranges[type].max_len);
 			err = 5;
@@ -362,12 +362,12 @@
 
 		cmp = keys_cmp(c, key1, key2);
 		if (cmp > 0) {
-			ubifs_err("bad key order (keys %d and %d)", i, i + 1);
+			ubifs_err(c, "bad key order (keys %d and %d)", i, i + 1);
 			err = 6;
 			goto out_dump;
 		} else if (cmp == 0 && !is_hash_key(c, key1)) {
 			/* These can only be keys with colliding hash */
-			ubifs_err("keys %d and %d are not hashed but equivalent",
+			ubifs_err(c, "keys %d and %d are not hashed but equivalent",
 				  i, i + 1);
 			err = 7;
 			goto out_dump;
@@ -378,7 +378,7 @@
 	return 0;
 
 out_dump:
-	ubifs_err("bad indexing node at LEB %d:%d, error %d", lnum, offs, err);
+	ubifs_err(c, "bad indexing node at LEB %d:%d, error %d", lnum, offs, err);
 	ubifs_dump_node(c, idx);
 	kfree(idx);
 	return -EINVAL;
@@ -474,7 +474,7 @@
 	/* Make sure the key of the read node is correct */
 	key_read(c, node + UBIFS_KEY_OFFSET, &key1);
 	if (!keys_eq(c, key, &key1)) {
-		ubifs_err("bad key in node at LEB %d:%d",
+		ubifs_err(c, "bad key in node at LEB %d:%d",
 			  zbr->lnum, zbr->offs);
 		dbg_tnck(key, "looked for key ");
 		dbg_tnck(&key1, "but found node's key ");
diff --git a/fs/ubifs/ubifs.c b/fs/ubifs/ubifs.c
index d7f307b..50355e9 100644
--- a/fs/ubifs/ubifs.c
+++ b/fs/ubifs/ubifs.c
@@ -103,8 +103,8 @@
 	int compressor;
 };
 
-static inline struct crypto_comp *crypto_alloc_comp(const char *alg_name,
-						u32 type, u32 mask)
+static inline struct crypto_comp
+*crypto_alloc_comp(const char *alg_name, u32 type, u32 mask)
 {
 	struct ubifs_compressor *comp;
 	struct crypto_comp *ptr;
@@ -124,15 +124,16 @@
 		i++;
 	}
 	if (i >= UBIFS_COMPR_TYPES_CNT) {
-		ubifs_err("invalid compression type %s", alg_name);
+		dbg_gen("invalid compression type %s", alg_name);
 		free (ptr);
 		return NULL;
 	}
 	return ptr;
 }
-static inline int crypto_comp_decompress(struct crypto_comp *tfm,
-				const u8 *src, unsigned int slen,
-				u8 *dst, unsigned int *dlen)
+static inline int
+crypto_comp_decompress(const struct ubifs_info *c, struct crypto_comp *tfm,
+		       const u8 *src, unsigned int slen, u8 *dst,
+		       unsigned int *dlen)
 {
 	struct ubifs_compressor *compr = ubifs_compressors[tfm->compressor];
 	int err;
@@ -145,7 +146,7 @@
 
 	err = compr->decompress(src, slen, dst, (size_t *)dlen);
 	if (err)
-		ubifs_err("cannot decompress %d bytes, compressor %s, "
+		ubifs_err(c, "cannot decompress %d bytes, compressor %s, "
 			  "error %d", slen, compr->name, err);
 
 	return err;
@@ -172,21 +173,21 @@
  * The length of the uncompressed data is returned in @out_len. This functions
  * returns %0 on success or a negative error code on failure.
  */
-int ubifs_decompress(const void *in_buf, int in_len, void *out_buf,
-		     int *out_len, int compr_type)
+int ubifs_decompress(const struct ubifs_info *c, const void *in_buf,
+		     int in_len, void *out_buf, int *out_len, int compr_type)
 {
 	int err;
 	struct ubifs_compressor *compr;
 
 	if (unlikely(compr_type < 0 || compr_type >= UBIFS_COMPR_TYPES_CNT)) {
-		ubifs_err("invalid compression type %d", compr_type);
+		ubifs_err(c, "invalid compression type %d", compr_type);
 		return -EINVAL;
 	}
 
 	compr = ubifs_compressors[compr_type];
 
 	if (unlikely(!compr->capi_name)) {
-		ubifs_err("%s compression is not compiled in", compr->name);
+		ubifs_err(c, "%s compression is not compiled in", compr->name);
 		return -EINVAL;
 	}
 
@@ -198,13 +199,13 @@
 
 	if (compr->decomp_mutex)
 		mutex_lock(compr->decomp_mutex);
-	err = crypto_comp_decompress(compr->cc, in_buf, in_len, out_buf,
+	err = crypto_comp_decompress(c, compr->cc, in_buf, in_len, out_buf,
 				     (unsigned int *)out_len);
 	if (compr->decomp_mutex)
 		mutex_unlock(compr->decomp_mutex);
 	if (err)
-		ubifs_err("cannot decompress %d bytes, compressor %s, error %d",
-			  in_len, compr->name, err);
+		ubifs_err(c, "cannot decompress %d bytes, compressor %s,"
+			  " error %d", in_len, compr->name, err);
 
 	return err;
 }
@@ -229,8 +230,9 @@
 	if (compr->capi_name) {
 		compr->cc = crypto_alloc_comp(compr->capi_name, 0, 0);
 		if (IS_ERR(compr->cc)) {
-			ubifs_err("cannot initialize compressor %s, error %ld",
-				  compr->name, PTR_ERR(compr->cc));
+			dbg_gen("cannot initialize compressor %s,"
+				  " error %ld", compr->name,
+				  PTR_ERR(compr->cc));
 			return PTR_ERR(compr->cc);
 		}
 	}
@@ -384,7 +386,7 @@
 
 out:
 	if (err != -ENOENT) {
-		ubifs_err("cannot find next direntry, error %d", err);
+		ubifs_err(c, "cannot find next direntry, error %d", err);
 		return err;
 	}
 
@@ -468,7 +470,7 @@
 
 out:
 	if (err != -ENOENT)
-		ubifs_err("cannot find next direntry, error %d", err);
+		dbg_gen("cannot find next direntry, error %d", err);
 
 out_free:
 	if (file->private_data)
@@ -715,7 +717,7 @@
 
 	dlen = le32_to_cpu(dn->ch.len) - UBIFS_DATA_NODE_SZ;
 	out_len = UBIFS_BLOCK_SIZE;
-	err = ubifs_decompress(&dn->data, dlen, addr, &out_len,
+	err = ubifs_decompress(c, &dn->data, dlen, addr, &out_len,
 			       le16_to_cpu(dn->compr_type));
 	if (err || len != out_len)
 		goto dump;
@@ -731,7 +733,7 @@
 	return 0;
 
 dump:
-	ubifs_err("bad data node (block %u, inode %lu)",
+	ubifs_err(c, "bad data node (block %u, inode %lu)",
 		  block, inode->i_ino);
 	ubifs_dump_node(c, dn);
 	return -EINVAL;
@@ -833,7 +835,7 @@
 			dbg_gen("hole");
 			goto out_free;
 		}
-		ubifs_err("cannot read page %lu of inode %lu, error %d",
+		ubifs_err(c, "cannot read page %lu of inode %lu, error %d",
 			  page->index, inode->i_ino, err);
 		goto error;
 	}
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index 225965c..1d89465 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -29,6 +29,7 @@
 #include <linux/mtd/ubi.h>
 #include <linux/pagemap.h>
 #include <linux/backing-dev.h>
+#include <linux/security.h>
 #include "ubifs-media.h"
 #else
 #include <asm/atomic.h>
@@ -617,24 +618,43 @@
 #define UBIFS_VERSION 1
 
 /* Normal UBIFS messages */
-#define ubifs_msg(fmt, ...) pr_notice("UBIFS: " fmt "\n", ##__VA_ARGS__)
+#define ubifs_msg(c, fmt, ...)                                      \
+	pr_notice("UBIFS (ubi%d:%d): " fmt "\n",                    \
+		  (c)->vi.ubi_num, (c)->vi.vol_id, ##__VA_ARGS__)
 /* UBIFS error messages */
 #ifndef __UBOOT__
-#define ubifs_err(fmt, ...)                                         \
-	pr_err("UBIFS error (pid %d): %s: " fmt "\n", current->pid, \
+#define ubifs_err(c, fmt, ...)                                      \
+	pr_err("UBIFS error (ubi%d:%d pid %d): %s: " fmt "\n",      \
+	       (c)->vi.ubi_num, (c)->vi.vol_id, current->pid,       \
 	       __func__, ##__VA_ARGS__)
 /* UBIFS warning messages */
-#define ubifs_warn(fmt, ...)                                        \
-	pr_warn("UBIFS warning (pid %d): %s: " fmt "\n",            \
-		current->pid, __func__, ##__VA_ARGS__)
+#define ubifs_warn(c, fmt, ...)                                     \
+	pr_warn("UBIFS warning (ubi%d:%d pid %d): %s: " fmt "\n",   \
+		(c)->vi.ubi_num, (c)->vi.vol_id, current->pid,      \
+		__func__, ##__VA_ARGS__)
 #else
-#define ubifs_err(fmt, ...)                                         \
-	pr_err("UBIFS error: %s: " fmt "\n", __func__, ##__VA_ARGS__)
+#define ubifs_err(c, fmt, ...)                                      \
+	pr_err("UBIFS error (ubi%d:%d pid %d): %s: " fmt "\n",      \
+	       (c)->vi.ubi_num, (c)->vi.vol_id, 0,                  \
+	       __func__, ##__VA_ARGS__)
 /* UBIFS warning messages */
-#define ubifs_warn(fmt, ...)                                        \
-	pr_warn("UBIFS warning: %s: " fmt "\n", __func__, ##__VA_ARGS__)
+#define ubifs_warn(c, fmt, ...)                                     \
+	pr_warn("UBIFS warning (ubi%d:%d pid %d): %s: " fmt "\n",   \
+		(c)->vi.ubi_num, (c)->vi.vol_id, 0,                 \
+		__func__, ##__VA_ARGS__)
+
 #endif
 
+/*
+ * A variant of 'ubifs_err()' which takes the UBIFS file-sytem description
+ * object as an argument.
+ */
+#define ubifs_errc(c, fmt, ...)                                     \
+	do {                                                        \
+		if (!(c)->probing)                                  \
+			ubifs_err(c, fmt, ##__VA_ARGS__);           \
+	} while (0)
+
 /* UBIFS file system VFS magic number */
 #define UBIFS_SUPER_MAGIC 0x24051905
 
@@ -731,7 +751,7 @@
 #define WORST_COMPR_FACTOR 2
 
 /*
- * How much memory is needed for a buffer where we comress a data node.
+ * How much memory is needed for a buffer where we compress a data node.
  */
 #define COMPRESSED_DATA_NODE_BUF_SZ \
 	(UBIFS_DATA_NODE_SZ + UBIFS_BLOCK_SIZE * WORST_COMPR_FACTOR)
@@ -888,7 +908,6 @@
  * @nodes_cnt: number of nodes scanned
  * @nodes: list of struct ubifs_scan_node
  * @endpt: end point (and therefore the start of empty space)
- * @ecc: read returned -EBADMSG
  * @buf: buffer containing entire LEB scanned
  */
 struct ubifs_scan_leb {
@@ -896,7 +915,6 @@
 	int nodes_cnt;
 	struct list_head nodes;
 	int endpt;
-	int ecc;
 	void *buf;
 };
 
@@ -1239,7 +1257,7 @@
  * @lock: serializes @buf, @lnum, @offs, @avail, @used, @next_ino and @inodes
  *        fields
  * @softlimit: soft write-buffer timeout interval
- * @delta: hard and soft timeouts delta (the timer expire inteval is @softlimit
+ * @delta: hard and soft timeouts delta (the timer expire interval is @softlimit
  *         and @softlimit + @delta)
  * @timer: write-buffer timer
  * @no_timer: non-zero if this write-buffer does not have a timer
@@ -1509,9 +1527,9 @@
 /**
  * struct ubifs_mount_opts - UBIFS-specific mount options information.
  * @unmount_mode: selected unmount mode (%0 default, %1 normal, %2 fast)
- * @bulk_read: enable/disable bulk-reads (%0 default, %1 disabe, %2 enable)
+ * @bulk_read: enable/disable bulk-reads (%0 default, %1 disable, %2 enable)
  * @chk_data_crc: enable/disable CRC data checking when reading data nodes
- *                (%0 default, %1 disabe, %2 enable)
+ *                (%0 default, %1 disable, %2 enable)
  * @override_compr: override default compressor (%0 - do not override and use
  *                  superblock compressor, %1 - override and use compressor
  *                  specified in @compr_type)
@@ -1541,9 +1559,9 @@
  *           optimization)
  * @nospace_rp: the same as @nospace, but additionally means that even reserved
  *              pool is full
- * @page_budget: budget for a page (constant, nenver changed after mount)
- * @inode_budget: budget for an inode (constant, nenver changed after mount)
- * @dent_budget: budget for a directory entry (constant, nenver changed after
+ * @page_budget: budget for a page (constant, never changed after mount)
+ * @inode_budget: budget for an inode (constant, never changed after mount)
+ * @dent_budget: budget for a directory entry (constant, never changed after
  *               mount)
  */
 struct ubifs_budg_info {
@@ -1629,7 +1647,6 @@
  *
  * @mst_node: master node
  * @mst_offs: offset of valid master node
- * @mst_mutex: protects the master node area, @mst_node, and @mst_offs
  *
  * @max_bu_buf_len: maximum bulk-read buffer length
  * @bu_mutex: protects the pre-allocated bulk-read buffer and @c->bu
@@ -1796,6 +1813,7 @@
  * @need_recovery: %1 if the file-system needs recovery
  * @replaying: %1 during journal replay
  * @mounting: %1 while mounting
+ * @probing: %1 while attempting to mount if MS_SILENT mount flag is set
  * @remounting_rw: %1 while re-mounting from R/O mode to R/W mode
  * @replay_list: temporary list used during journal replay
  * @replay_buds: list of buds to replay
@@ -1871,7 +1889,6 @@
 
 	struct ubifs_mst_node *mst_node;
 	int mst_offs;
-	struct mutex mst_mutex;
 
 	int max_bu_buf_len;
 	struct mutex bu_mutex;
@@ -2030,6 +2047,7 @@
 	unsigned int replaying:1;
 	unsigned int mounting:1;
 	unsigned int remounting_rw:1;
+	unsigned int probing:1;
 	struct list_head replay_list;
 	struct list_head replay_buds;
 	unsigned long long cs_sqnum;
@@ -2049,6 +2067,7 @@
 extern atomic_long_t ubifs_clean_zn_cnt;
 extern struct kmem_cache *ubifs_inode_slab;
 extern const struct super_operations ubifs_super_operations;
+extern const struct xattr_handler *ubifs_xattr_handlers[];
 extern const struct address_space_operations ubifs_file_address_operations;
 extern const struct file_operations ubifs_file_operations;
 extern const struct inode_operations ubifs_file_inode_operations;
@@ -2340,6 +2359,8 @@
 		       size_t size);
 ssize_t ubifs_listxattr(struct dentry *dentry, char *buffer, size_t size);
 int ubifs_removexattr(struct dentry *dentry, const char *name);
+int ubifs_init_security(struct inode *dentry, struct inode *inode,
+			const struct qstr *qstr);
 
 /* super.c */
 struct inode *ubifs_iget(struct super_block *sb, unsigned long inum);
@@ -2370,10 +2391,10 @@
 /* compressor.c */
 int __init ubifs_compressors_init(void);
 void ubifs_compressors_exit(void);
-void ubifs_compress(const void *in_buf, int in_len, void *out_buf, int *out_len,
-		    int *compr_type);
-int ubifs_decompress(const void *buf, int len, void *out, int *out_len,
-		     int compr_type);
+void ubifs_compress(const struct ubifs_info *c, const void *in_buf, int in_len,
+		    void *out_buf, int *out_len, int *compr_type);
+int ubifs_decompress(const struct ubifs_info *c, const void *buf, int len,
+		     void *out, int *out_len, int compr_type);
 
 #include "debug.h"
 #include "misc.h"
diff --git a/include/configs/ebony.h b/include/configs/ebony.h
deleted file mode 100644
index 3f0ad69..0000000
--- a/include/configs/ebony.h
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * (C) Copyright 2002 Scott McNutt <smcnutt@artesyncp.com>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-/************************************************************************
- * board/config_EBONY.h - configuration for AMCC 440GP Ref (Ebony)
- ***********************************************************************/
-
-#ifndef __CONFIG_H
-#define __CONFIG_H
-
-/*-----------------------------------------------------------------------
- * High Level Configuration Options
- *----------------------------------------------------------------------*/
-#define CONFIG_EBONY		1	    /* Board is ebony		*/
-#define CONFIG_440GP		1	    /* Specifc GP support	*/
-#define CONFIG_440		1	    /* ... PPC440 family	*/
-#define CONFIG_BOARD_EARLY_INIT_F 1	    /* Call board_early_init_f	*/
-#define CONFIG_SYS_CLK_FREQ	33333333    /* external freq to pll	*/
-
-#define	CONFIG_SYS_TEXT_BASE	0xFFFC0000
-
-/*
- * Include common defines/options for all AMCC eval boards
- */
-#define CONFIG_HOSTNAME		ebony
-#include "amcc-common.h"
-
-/*
- * Define here the location of the environment variables (FLASH or NVRAM).
- * Note: DENX encourages to use redundant environment in FLASH. NVRAM is only
- *       supported for backward compatibility.
- */
-#if 1
-#define CONFIG_ENV_IS_IN_FLASH     1	/* use FLASH for environment vars	*/
-#else
-#define CONFIG_ENV_IS_IN_NVRAM	1	/* use NVRAM for environment vars	*/
-#endif
-
-/*-----------------------------------------------------------------------
- * Base addresses -- Note these are effective addresses where the
- * actual resources get mapped (not physical addresses)
- *----------------------------------------------------------------------*/
-#define CONFIG_SYS_SDRAM_BASE	    0x00000000	    /* _must_ be 0		*/
-#define CONFIG_SYS_FLASH_BASE	    0xff800000	    /* start of FLASH		*/
-#define CONFIG_SYS_PCI_MEMBASE	    0x80000000	    /* mapped pci memory	*/
-#define CONFIG_SYS_ISRAM_BASE	    0xc0000000	    /* internal SRAM		*/
-#define CONFIG_SYS_PCI_BASE	    0xd0000000	    /* internal PCI regs	*/
-
-#define CONFIG_SYS_NVRAM_BASE_ADDR (CONFIG_SYS_PERIPHERAL_BASE + 0x08000000)
-#define CONFIG_SYS_FPGA_BASE	    (CONFIG_SYS_PERIPHERAL_BASE + 0x08300000)
-
-/*-----------------------------------------------------------------------
- * Initial RAM & stack pointer (placed in internal SRAM)
- *----------------------------------------------------------------------*/
-#define CONFIG_SYS_INIT_RAM_ADDR   CONFIG_SYS_ISRAM_BASE  /* Initial RAM address	*/
-#define CONFIG_SYS_INIT_RAM_SIZE    0x2000	    /* Size of used area in RAM	*/
-
-#define CONFIG_SYS_GBL_DATA_OFFSET	(CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE)
-#define CONFIG_SYS_INIT_SP_OFFSET	CONFIG_SYS_GBL_DATA_OFFSET
-
-/*-----------------------------------------------------------------------
- * Serial Port
- *----------------------------------------------------------------------*/
-#define CONFIG_CONS_INDEX	1	/* Use UART0			*/
-#define CONFIG_SYS_EXT_SERIAL_CLOCK	(1843200 * 6)	/* Ext clk @ 11.059 MHz */
-
-/*-----------------------------------------------------------------------
- * NVRAM/RTC
- *
- * NOTE: Upper 8 bytes of NVRAM is where the RTC registers are located.
- * The DS1743 code assumes this condition (i.e. -- it assumes the base
- * address for the RTC registers is:
- *
- *	CONFIG_SYS_NVRAM_BASE_ADDR + CONFIG_SYS_NVRAM_SIZE
- *
- *----------------------------------------------------------------------*/
-#define CONFIG_SYS_NVRAM_SIZE	    (0x2000 - 8)    /* NVRAM size(8k)- RTC regs */
-#define CONFIG_RTC_DS174x	1		    /* DS1743 RTC		*/
-
-#ifdef CONFIG_ENV_IS_IN_NVRAM
-#define CONFIG_ENV_SIZE		0x1000	    /* Size of Environment vars */
-#define CONFIG_ENV_ADDR		\
-	(CONFIG_SYS_NVRAM_BASE_ADDR+CONFIG_SYS_NVRAM_SIZE-CONFIG_ENV_SIZE)
-#endif /* CONFIG_ENV_IS_IN_NVRAM */
-
-/*-----------------------------------------------------------------------
- * FLASH related
- *----------------------------------------------------------------------*/
-#define CONFIG_SYS_MAX_FLASH_BANKS	3		    /* number of banks	    */
-#define CONFIG_SYS_MAX_FLASH_SECT	32		    /* sectors per device   */
-
-#define CONFIG_SYS_FLASH_ERASE_TOUT	120000	/* Timeout for Flash Erase (in ms)	*/
-#define CONFIG_SYS_FLASH_WRITE_TOUT	500	/* Timeout for Flash Write (in ms)	*/
-
-#define CONFIG_SYS_FLASH_EMPTY_INFO		/* print 'E' for empty sector on flinfo */
-
-#define CONFIG_SYS_FLASH_ADDR0         0x5555
-#define CONFIG_SYS_FLASH_ADDR1         0x2aaa
-#define CONFIG_SYS_FLASH_WORD_SIZE     unsigned char
-
-#ifdef CONFIG_ENV_IS_IN_FLASH
-#define CONFIG_ENV_SECT_SIZE	0x10000	/* size of one complete sector		*/
-#define CONFIG_ENV_ADDR		(CONFIG_SYS_MONITOR_BASE-CONFIG_ENV_SECT_SIZE)
-#define	CONFIG_ENV_SIZE		0x4000	/* Total Size of Environment Sector	*/
-
-/* Address and size of Redundant Environment Sector	*/
-#define CONFIG_ENV_ADDR_REDUND	(CONFIG_ENV_ADDR-CONFIG_ENV_SECT_SIZE)
-#define CONFIG_ENV_SIZE_REDUND	(CONFIG_ENV_SIZE)
-#endif /* CONFIG_ENV_IS_IN_FLASH */
-
-/*-----------------------------------------------------------------------
- * DDR SDRAM
- *----------------------------------------------------------------------*/
-#define CONFIG_SPD_EEPROM	1	/* Use SPD EEPROM for setup	*/
-#define SPD_EEPROM_ADDRESS {0x53,0x52}	/* SPD i2c spd addresses	*/
-#define CONFIG_PROG_SDRAM_TLB	1	/* setup SDRAM TLB's dynamically*/
-
-/*-----------------------------------------------------------------------
- * I2C
- *----------------------------------------------------------------------*/
-#define CONFIG_SYS_I2C_PPC4XX_SPEED_0		400000
-
-#define CONFIG_SYS_I2C_MULTI_EEPROMS
-#define CONFIG_SYS_I2C_EEPROM_ADDR	(0xa8>>1)
-#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 1
-#define CONFIG_SYS_EEPROM_PAGE_WRITE_BITS 3
-#define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS 10
-
-/*
- * Default environment variables
- */
-#define	CONFIG_EXTRA_ENV_SETTINGS					\
-	CONFIG_AMCC_DEF_ENV						\
-	CONFIG_AMCC_DEF_ENV_POWERPC					\
-	CONFIG_AMCC_DEF_ENV_PPC_OLD					\
-	CONFIG_AMCC_DEF_ENV_NOR_UPD					\
-	"kernel_addr=ff800000\0"					\
-	"ramdisk_addr=ff810000\0"					\
-	""
-
-#define CONFIG_PHY_ADDR		8	/* PHY address			*/
-#define CONFIG_HAS_ETH0
-#define CONFIG_HAS_ETH1
-#define CONFIG_PHY1_ADDR	9	/* EMAC1 PHY address		*/
-
-/*
- * Commands additional to the ones defined in amcc-common.h
- */
-#define CONFIG_CMD_DATE
-#define CONFIG_CMD_PCI
-#define CONFIG_CMD_SDRAM
-#define CONFIG_CMD_SNTP
-
-/*-----------------------------------------------------------------------
- * PCI stuff
- *-----------------------------------------------------------------------
- */
-/* General PCI */
-#define CONFIG_PCI			            /* include pci support	        */
-#define CONFIG_PCI_INDIRECT_BRIDGE	/* indirect PCI bridge support */
-#define CONFIG_PCI_PNP			        /* do pci plug-and-play         */
-#define CONFIG_PCI_SCAN_SHOW            /* show pci devices on startup  */
-#define CONFIG_SYS_PCI_TARGBASE    0x80000000  /* PCIaddr mapped to CONFIG_SYS_PCI_MEMBASE */
-
-/* Board-specific PCI */
-#define CONFIG_SYS_PCI_TARGET_INIT	            /* let board init pci target    */
-
-#define CONFIG_SYS_PCI_SUBSYS_VENDORID 0x10e8	/* AMCC */
-#define CONFIG_SYS_PCI_SUBSYS_DEVICEID 0xcafe  /* Whatever */
-
-#endif	/* __CONFIG_H */
diff --git a/include/configs/ocotea.h b/include/configs/ocotea.h
deleted file mode 100644
index 4ff2f05..0000000
--- a/include/configs/ocotea.h
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * (C) Copyright 2004 Paul Reynolds <PaulReynolds@lhsolutions.com>
- *
- * (C) Copyright 2005
- * Stefan Roese, DENX Software Engineering, sr@denx.de.
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-/************************************************************************
- * 1 March 2004	 Travis B. Sawyer <tsawyer@sandburst.com>
- * Adapted to current Das U-Boot source
- ***********************************************************************/
-
-
-/************************************************************************
- * OCOTEA.h - configuration for AMCC 440GX Ref (Ocotea)
- ***********************************************************************/
-
-#ifndef __CONFIG_H
-#define __CONFIG_H
-
-/*-----------------------------------------------------------------------
- * High Level Configuration Options
- *----------------------------------------------------------------------*/
-#define CONFIG_OCOTEA		1	    /* Board is ebony		*/
-#define CONFIG_440GX		1	    /* Specifc GX support	*/
-#define CONFIG_440		1	    /* ... PPC440 family	*/
-#define CONFIG_BOARD_EARLY_INIT_F 1	    /* Call board_pre_init	*/
-#define CONFIG_SYS_CLK_FREQ	33333333    /* external freq to pll	*/
-
-#define	CONFIG_SYS_TEXT_BASE	0xFFFC0000
-
-/*
- * Include common defines/options for all AMCC eval boards
- */
-#define CONFIG_HOSTNAME		ocotea
-#include "amcc-common.h"
-
-/*-----------------------------------------------------------------------
- * Base addresses -- Note these are effective addresses where the
- * actual resources get mapped (not physical addresses)
- *----------------------------------------------------------------------*/
-#define CONFIG_SYS_FLASH_BASE	    0xff800000	    /* start of FLASH		*/
-#define CONFIG_SYS_PCI_MEMBASE	    0x80000000	    /* mapped pci memory	*/
-#define CONFIG_SYS_ISRAM_BASE	    0xc0000000	    /* internal SRAM		*/
-#define CONFIG_SYS_PCI_BASE	    0xd0000000	    /* internal PCI regs	*/
-
-#define CONFIG_SYS_FPGA_BASE	    (CONFIG_SYS_PERIPHERAL_BASE + 0x08300000)
-#define CONFIG_SYS_NVRAM_BASE_ADDR (CONFIG_SYS_PERIPHERAL_BASE + 0x08000000)
-
-/*-----------------------------------------------------------------------
- * Initial RAM & stack pointer (placed in internal SRAM)
- *----------------------------------------------------------------------*/
-#define CONFIG_SYS_TEMP_STACK_OCM  1
-#define CONFIG_SYS_OCM_DATA_ADDR   CONFIG_SYS_ISRAM_BASE
-#define CONFIG_SYS_INIT_RAM_ADDR   CONFIG_SYS_ISRAM_BASE  /* Initial RAM address	*/
-#define CONFIG_SYS_INIT_RAM_SIZE    0x2000	    /* Size of used area in RAM	*/
-
-#define CONFIG_SYS_GBL_DATA_OFFSET	(CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE)
-#define CONFIG_SYS_INIT_SP_OFFSET	(CONFIG_SYS_GBL_DATA_OFFSET - 0x4)
-
-/*-----------------------------------------------------------------------
- * Serial Port
- *----------------------------------------------------------------------*/
-#define CONFIG_CONS_INDEX	1	/* Use UART0			*/
-#define CONFIG_SYS_EXT_SERIAL_CLOCK	(1843200 * 6)	/* Ext clk @ 11.059 MHz */
-
-/*-----------------------------------------------------------------------
- * Environment
- *----------------------------------------------------------------------*/
-/*
- * Define here the location of the environment variables (FLASH or NVRAM).
- * Note: DENX encourages to use redundant environment in FLASH. NVRAM is only
- *       supported for backward compatibility.
- */
-#if 1
-#define CONFIG_ENV_IS_IN_FLASH     1	/* use FLASH for environment vars	*/
-#else
-#define CONFIG_ENV_IS_IN_NVRAM	1	/* use NVRAM for environment vars	*/
-#endif
-
-
-/*-----------------------------------------------------------------------
- * NVRAM/RTC
- *
- * NOTE: Upper 8 bytes of NVRAM is where the RTC registers are located.
- * The DS1743 code assumes this condition (i.e. -- it assumes the base
- * address for the RTC registers is:
- *
- *	CONFIG_SYS_NVRAM_BASE_ADDR + CONFIG_SYS_NVRAM_SIZE
- *
- *----------------------------------------------------------------------*/
-#define CONFIG_SYS_NVRAM_SIZE	    (0x2000 - 8)    /* NVRAM size(8k)- RTC regs */
-#define CONFIG_RTC_DS174x	1		    /* DS1743 RTC		*/
-
-#ifdef CONFIG_ENV_IS_IN_NVRAM
-#define CONFIG_ENV_SIZE		0x1000	    /* Size of Environment vars */
-#define CONFIG_ENV_ADDR		\
-	(CONFIG_SYS_NVRAM_BASE_ADDR+CONFIG_SYS_NVRAM_SIZE-CONFIG_ENV_SIZE)
-#endif /* CONFIG_ENV_IS_IN_NVRAM */
-
-/*-----------------------------------------------------------------------
- * FLASH related
- *----------------------------------------------------------------------*/
-#define CONFIG_SYS_MAX_FLASH_BANKS	3		    /* number of banks	    */
-#define CONFIG_SYS_MAX_FLASH_SECT	64		    /* sectors per device   */
-
-#undef	CONFIG_SYS_FLASH_CHECKSUM
-#define CONFIG_SYS_FLASH_ERASE_TOUT	120000	/* Timeout for Flash Erase (in ms)	*/
-#define CONFIG_SYS_FLASH_WRITE_TOUT	500	/* Timeout for Flash Write (in ms)	*/
-
-#define CONFIG_SYS_FLASH_ADDR0         0x5555
-#define CONFIG_SYS_FLASH_ADDR1         0x2aaa
-#define CONFIG_SYS_FLASH_WORD_SIZE     unsigned char
-
-#ifdef CONFIG_ENV_IS_IN_FLASH
-#define CONFIG_ENV_SECT_SIZE	0x10000		/* size of one complete sector	*/
-#define CONFIG_ENV_ADDR		(CONFIG_SYS_MONITOR_BASE-CONFIG_ENV_SECT_SIZE)
-#define	CONFIG_ENV_SIZE		0x4000	/* Total Size of Environment Sector	*/
-
-/* Address and size of Redundant Environment Sector	*/
-#define CONFIG_ENV_ADDR_REDUND	(CONFIG_ENV_ADDR-CONFIG_ENV_SECT_SIZE)
-#define CONFIG_ENV_SIZE_REDUND	(CONFIG_ENV_SIZE)
-#endif /* CONFIG_ENV_IS_IN_FLASH */
-
-/*-----------------------------------------------------------------------
- * DDR SDRAM
- *----------------------------------------------------------------------*/
-#define CONFIG_SPD_EEPROM	1	/* Use SPD EEPROM for setup	*/
-#define SPD_EEPROM_ADDRESS {0x53,0x52}	/* SPD i2c spd addresses	*/
-#define CONFIG_PROG_SDRAM_TLB	1	/* setup SDRAM TLB's dynamically*/
-
-/*-----------------------------------------------------------------------
- * I2C
- *----------------------------------------------------------------------*/
-#define CONFIG_SYS_I2C_PPC4XX_SPEED_0		400000
-
-#define CONFIG_SYS_I2C_MULTI_EEPROMS
-#define CONFIG_SYS_I2C_EEPROM_ADDR	(0xa8>>1)
-#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 1
-#define CONFIG_SYS_EEPROM_PAGE_WRITE_BITS 3
-#define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS 10
-
-/*
- * Default environment variables
- */
-#define	CONFIG_EXTRA_ENV_SETTINGS					\
-	CONFIG_AMCC_DEF_ENV						\
-	CONFIG_AMCC_DEF_ENV_PPC						\
-	CONFIG_AMCC_DEF_ENV_NOR_UPD					\
-	"kernel_addr=fff00000\0"					\
-	"ramdisk_addr=fff10000\0"					\
-	""
-
-#define CONFIG_PHY_ADDR		1	/* PHY address, See schematics	*/
-#define CONFIG_PHY1_ADDR	2
-#define CONFIG_PHY2_ADDR	0x10
-#define CONFIG_PHY3_ADDR	0x18
-#define CONFIG_HAS_ETH0
-#define CONFIG_HAS_ETH1
-#define CONFIG_HAS_ETH2
-#define CONFIG_HAS_ETH3
-#define CONFIG_CIS8201_PHY	1	/* Enable 'special' RGMII mode for Cicada phy */
-#define CONFIG_PHY_GIGE		1	/* Include GbE speed/duplex detection */
-#define CONFIG_PHY_RESET        1       /* reset phy upon startup         */
-#define CONFIG_PHY_RESET_DELAY	1000
-
-/*
- * Commands additional to the ones defined in amcc-common.h
- */
-#define CONFIG_CMD_DATE
-#define CONFIG_CMD_PCI
-#define CONFIG_CMD_SDRAM
-#define CONFIG_CMD_SNTP
-
-/*-----------------------------------------------------------------------
- * PCI stuff
- *-----------------------------------------------------------------------
- */
-/* General PCI */
-#define CONFIG_PCI			/* include pci support		*/
-#define CONFIG_PCI_INDIRECT_BRIDGE	/* indirect PCI bridge support */
-#define CONFIG_PCI_PNP			/* do pci plug-and-play		*/
-#define CONFIG_PCI_SCAN_SHOW		/* show pci devices on startup	*/
-#define CONFIG_SYS_PCI_TARGBASE    0x80000000	/* PCIaddr mapped to CONFIG_SYS_PCI_MEMBASE */
-
-/* Board-specific PCI */
-#define CONFIG_SYS_PCI_TARGET_INIT		/* let board init pci target    */
-
-#define CONFIG_SYS_PCI_SUBSYS_VENDORID 0x10e8	/* AMCC */
-#define CONFIG_SYS_PCI_SUBSYS_DEVICEID 0xcafe	/* Whatever */
-
-#endif	/* __CONFIG_H */
diff --git a/include/configs/taihu.h b/include/configs/taihu.h
deleted file mode 100644
index 5c0ce7a..0000000
--- a/include/configs/taihu.h
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
- * (C) Copyright 2000-2005
- * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
- *
- * (C) Copyright 2005-2007
- * Beijing UD Technology Co., Ltd., taihusupport@amcc.com
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#ifndef __CONFIG_H
-#define __CONFIG_H
-
-
-#define CONFIG_405EP		1	/* this is a PPC405 CPU */
-#define CONFIG_TAIHU	        1	/*  on a taihu board */
-
-#define	CONFIG_SYS_TEXT_BASE	0xFFFC0000
-
-/*
- * Include common defines/options for all AMCC eval boards
- */
-#define CONFIG_HOSTNAME		taihu
-#include "amcc-common.h"
-
-#define CONFIG_BOARD_EARLY_INIT_F 1	/* call board_early_init_f */
-
-#define CONFIG_SYS_CLK_FREQ     33000000 /* external frequency to pll   */
-
-#define CONFIG_NO_SERIAL_EEPROM
-
-/*----------------------------------------------------------------------------*/
-#ifdef CONFIG_NO_SERIAL_EEPROM
-
-/*
-!-------------------------------------------------------------------------------
-! PLL settings for 333MHz CPU, 111MHz PLB/SDRAM, 55MHz EBC, 33MHz PCI,
-! assuming a 33MHz input clock to the 405EP from the C9531.
-!-------------------------------------------------------------------------------
-*/
-#define PLLMR0_333_111_55_37 (PLL_CPUDIV_1 | PLL_PLBDIV_3 |  \
-			      PLL_OPBDIV_2 | PLL_EXTBUSDIV_2 |  \
-			      PLL_MALDIV_1 | PLL_PCIDIV_3)
-#define PLLMR1_333_111_55_37 (PLL_FBKDIV_10  |  \
-			      PLL_FWDDIVA_3 | PLL_FWDDIVB_3 |  \
-			      PLL_TUNE_15_M_40 | PLL_TUNE_VCO_HI)
-#define PLLMR0_333_111_55_111 (PLL_CPUDIV_1 | PLL_PLBDIV_3 |  \
-			       PLL_OPBDIV_2 | PLL_EXTBUSDIV_2 |  \
-			       PLL_MALDIV_1 | PLL_PCIDIV_1)
-#define PLLMR1_333_111_55_111 (PLL_FBKDIV_10  |  \
-			       PLL_FWDDIVA_3 | PLL_FWDDIVB_3 |  \
-			       PLL_TUNE_15_M_40 | PLL_TUNE_VCO_HI)
-
-#define PLLMR0_DEFAULT		PLLMR0_333_111_55_37
-#define PLLMR1_DEFAULT		PLLMR1_333_111_55_37
-#define PLLMR0_DEFAULT_PCI66	PLLMR0_333_111_55_111
-#define PLLMR1_DEFAULT_PCI66	PLLMR1_333_111_55_111
-
-#endif
-/*----------------------------------------------------------------------------*/
-
-#define CONFIG_ENV_IS_IN_FLASH     1	/* use FLASH for environment vars */
-
-/*
- * Default environment variables
- */
-#define	CONFIG_EXTRA_ENV_SETTINGS					\
-	CONFIG_AMCC_DEF_ENV						\
-	CONFIG_AMCC_DEF_ENV_PPC						\
-	CONFIG_AMCC_DEF_ENV_NOR_UPD					\
-	"kernel_addr=FC000000\0"					\
-	"ramdisk_addr=FC180000\0"					\
-	""
-
-#define CONFIG_PHY_ADDR		0x14	/* PHY address			*/
-#define CONFIG_HAS_ETH0
-#define CONFIG_HAS_ETH1
-#define CONFIG_PHY1_ADDR	0x10	/* EMAC1 PHY address		*/
-#define CONFIG_PHY_RESET	1
-
-/*
- * Commands additional to the ones defined in amcc-common.h
- */
-#define CONFIG_CMD_CACHE
-#define CONFIG_CMD_PCI
-#define CONFIG_CMD_SDRAM
-#define CONFIG_CMD_SPI
-
-#undef CONFIG_SPD_EEPROM		/* use SPD EEPROM for setup */
-#define CONFIG_SYS_SDRAM_SIZE_PER_BANK 0x04000000 /* 64MB */
-#define CONFIG_SYS_SDRAM_BANKS	        2
-
-/*
- * SDRAM configuration (please see cpu/ppc/sdram.[ch])
- */
-#define CONFIG_SDRAM_BANK0	1	/* init onboard SDRAM bank 0 */
-#define CONFIG_SDRAM_BANK1	1	/* init onboard SDRAM bank 1 */
-
-/* SDRAM timings used in datasheet */
-#define CONFIG_SYS_SDRAM_CL            3	/* CAS latency */
-#define CONFIG_SYS_SDRAM_tRP           20	/* PRECHARGE command period */
-#define CONFIG_SYS_SDRAM_tRC           66	/* ACTIVE-to-ACTIVE command period */
-#define CONFIG_SYS_SDRAM_tRCD          20	/* ACTIVE-to-READ delay */
-#define CONFIG_SYS_SDRAM_tRFC		66	/* Auto refresh period */
-
-/*
- * If CONFIG_SYS_EXT_SERIAL_CLOCK, then the UART divisor is 1.
- * If CONFIG_SYS_405_UART_ERRATA_59, then UART divisor is 31.
- * Otherwise, UART divisor is determined by CPU Clock and CONFIG_SYS_BASE_BAUD value.
- * The Linux BASE_BAUD define should match this configuration.
- *    baseBaud = cpuClock/(uartDivisor*16)
- * If CONFIG_SYS_405_UART_ERRATA_59 and 200MHz CPU clock,
- * set Linux BASE_BAUD to 403200.
- */
-#define CONFIG_CONS_INDEX	2	/* Use UART1			*/
-#undef  CONFIG_SYS_EXT_SERIAL_CLOCK           /* external serial clock */
-#undef  CONFIG_SYS_405_UART_ERRATA_59         /* 405GP/CR Rev. D silicon */
-#define CONFIG_SYS_BASE_BAUD		691200
-
-/*-----------------------------------------------------------------------
- * I2C stuff
- *-----------------------------------------------------------------------
- */
-#define CONFIG_SYS_I2C_PPC4XX_SPEED_0		400000
-
-#define CONFIG_SYS_I2C_NOPROBES	{ {0, 0x69} } /* avoid i2c probe hangup (?) */
-#define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS	6 /* 24C02 requires 5ms delay */
-
-#define CONFIG_SYS_I2C_EEPROM_ADDR	0x50	/* I2C boot EEPROM (24C02W)	*/
-#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN	1	/* Bytes of address		*/
-
-#define CONFIG_SOFT_SPI
-#define SPI_SCL  spi_scl
-#define SPI_SDA  spi_sda
-#define SPI_READ spi_read()
-#define SPI_DELAY udelay(2)
-#ifndef __ASSEMBLY__
-void spi_scl(int);
-void spi_sda(int);
-unsigned char spi_read(void);
-#endif
-
-/* standard dtt sensor configuration */
-#define CONFIG_DTT_DS1775	1
-#define CONFIG_DTT_SENSORS	{ 0 }
-#define CONFIG_SYS_I2C_DTT_ADDR	0x49
-
-/*-----------------------------------------------------------------------
- * PCI stuff
- *-----------------------------------------------------------------------
- */
-#define PCI_HOST_ADAPTER 0		/* configure ar pci adapter    */
-#define PCI_HOST_FORCE   1		/* configure as pci host       */
-#define PCI_HOST_AUTO    2		/* detected via arbiter enable */
-
-#define CONFIG_PCI			/* include pci support	       */
-#define CONFIG_PCI_INDIRECT_BRIDGE	/* indirect PCI bridge support */
-#define CONFIG_PCI_HOST	PCI_HOST_FORCE  /* select pci host function    */
-#define CONFIG_PCI_PNP			/* do pci plug-and-play        */
-					/* resource configuration      */
-#define CONFIG_PCI_SCAN_SHOW            /* show pci devices on startup */
-
-#define CONFIG_SYS_PCI_SUBSYS_VENDORID 0x10e8	/* AMCC */
-#define CONFIG_SYS_PCI_SUBSYS_DEVICEID 0xcafe	/* Whatever */
-#define CONFIG_SYS_PCI_CLASSCODE       0x0600  /* PCI Class Code: bridge/host */
-#define CONFIG_SYS_PCI_PTM1LA	    0x00000000	/* point to sdram              */
-#define CONFIG_SYS_PCI_PTM1MS      0x80000001	/* 2GB, enable hard-wired to 1 */
-#define CONFIG_SYS_PCI_PTM1PCI     0x00000000	/* Host: use this pci address  */
-#define CONFIG_SYS_PCI_PTM2LA      0x00000000	/* disabled                    */
-#define CONFIG_SYS_PCI_PTM2MS	    0x00000000	/* disabled                    */
-#define CONFIG_SYS_PCI_PTM2PCI     0x04000000	/* Host: use this pci address  */
-#define CONFIG_EEPRO100		1
-
-/*-----------------------------------------------------------------------
- * Start addresses for the final memory configuration
- * (Set up by the startup code)
- */
-#define CONFIG_SYS_FLASH_BASE		0xFFE00000
-
-/*-----------------------------------------------------------------------
- * FLASH organization
- */
-#define CONFIG_SYS_MAX_FLASH_BANKS	2	/* max number of memory banks		*/
-#define CONFIG_SYS_MAX_FLASH_SECT	256	/* max number of sectors on one chip	*/
-
-#define CONFIG_SYS_FLASH_ERASE_TOUT	120000	/* Timeout for Flash Erase (in ms)	*/
-#define CONFIG_SYS_FLASH_WRITE_TOUT	500	/* Timeout for Flash Write (in ms)	*/
-
-#define CONFIG_SYS_FLASH_ADDR0         0x555
-#define CONFIG_SYS_FLASH_ADDR1         0x2aa
-#define CONFIG_SYS_FLASH_WORD_SIZE     unsigned short
-
-#ifdef CONFIG_ENV_IS_IN_FLASH
-#define CONFIG_ENV_SECT_SIZE	0x10000	/* size of one complete sector	*/
-#define CONFIG_ENV_ADDR		(CONFIG_SYS_MONITOR_BASE-CONFIG_ENV_SECT_SIZE)
-#define CONFIG_ENV_SIZE		0x4000	/* Total Size of Environment Sector	*/
-
-/* Address and size of Redundant Environment Sector	*/
-#define CONFIG_ENV_ADDR_REDUND	(CONFIG_ENV_ADDR-CONFIG_ENV_SECT_SIZE)
-#define CONFIG_ENV_SIZE_REDUND	(CONFIG_ENV_SIZE)
-#endif /* CONFIG_ENV_IS_IN_FLASH */
-
-/*-----------------------------------------------------------------------
- * NVRAM organization
- */
-#define CONFIG_SYS_NVRAM_BASE_ADDR	0xf0000000	/* NVRAM base address */
-#define CONFIG_SYS_NVRAM_SIZE		0x1ff8		/* NVRAM size */
-
-#ifdef CONFIG_ENV_IS_IN_NVRAM
-#define CONFIG_ENV_SIZE		0x0ff8		/* Size of Environment vars */
-#define CONFIG_ENV_ADDR		\
-	(CONFIG_SYS_NVRAM_BASE_ADDR+CONFIG_SYS_NVRAM_SIZE-CONFIG_ENV_SIZE)	/* Env*/
-#endif
-
-/*-----------------------------------------------------------------------
- * PPC405 GPIO Configuration
- */
-#define CONFIG_SYS_4xx_GPIO_TABLE { /*				GPIO	Alternate1		*/	\
-{												\
-/* GPIO Core 0 */										\
-{ GPIO_BASE, GPIO_OUT, GPIO_SEL,  GPIO_OUT_NO_CHG }, /* GPIO0	PerBLast    SPI CS	*/	\
-{ GPIO_BASE, GPIO_OUT, GPIO_ALT1, GPIO_OUT_NO_CHG }, /* GPIO1	TS1E			*/	\
-{ GPIO_BASE, GPIO_OUT, GPIO_ALT1, GPIO_OUT_NO_CHG }, /* GPIO2	TS2E			*/	\
-{ GPIO_BASE, GPIO_OUT, GPIO_ALT1, GPIO_OUT_NO_CHG }, /* GPIO3	TS1O			*/	\
-{ GPIO_BASE, GPIO_OUT, GPIO_ALT1, GPIO_OUT_NO_CHG }, /* GPIO4	TS2O			*/	\
-{ GPIO_BASE, GPIO_OUT, GPIO_ALT1, GPIO_OUT_NO_CHG }, /* GPIO5	TS3			*/	\
-{ GPIO_BASE, GPIO_OUT, GPIO_ALT1, GPIO_OUT_NO_CHG }, /* GPIO6	TS4			*/	\
-{ GPIO_BASE, GPIO_OUT, GPIO_ALT1, GPIO_OUT_NO_CHG }, /* GPIO7	TS5			*/	\
-{ GPIO_BASE, GPIO_OUT, GPIO_ALT1, GPIO_OUT_NO_CHG }, /* GPIO8	TS6			*/	\
-{ GPIO_BASE, GPIO_OUT, GPIO_ALT1, GPIO_OUT_NO_CHG }, /* GPIO9	TrcClk			*/	\
-{ GPIO_BASE, GPIO_OUT, GPIO_ALT1, GPIO_OUT_NO_CHG }, /* GPIO10	PerCS1			*/	\
-{ GPIO_BASE, GPIO_OUT, GPIO_ALT1, GPIO_OUT_NO_CHG }, /* GPIO11	PerCS2			*/	\
-{ GPIO_BASE, GPIO_OUT, GPIO_ALT1, GPIO_OUT_NO_CHG }, /* GPIO12	PerCS3			*/	\
-{ GPIO_BASE, GPIO_OUT, GPIO_ALT1, GPIO_OUT_NO_CHG }, /* GPIO13	PerCS4			*/	\
-{ GPIO_BASE, GPIO_OUT, GPIO_SEL,  GPIO_OUT_NO_CHG }, /* GPIO14	PerAddr03   SPI SCLK	*/	\
-{ GPIO_BASE, GPIO_IN,  GPIO_SEL,  GPIO_OUT_NO_CHG }, /* GPIO15	PerAddr04   SPI DI	*/	\
-{ GPIO_BASE, GPIO_OUT, GPIO_SEL,  GPIO_OUT_NO_CHG }, /* GPIO16	PerAddr05   SPI DO	*/	\
-{ GPIO_BASE, GPIO_IN,  GPIO_ALT1, GPIO_OUT_NO_CHG }, /* GPIO17	IRQ0	    PCI INTA	*/	\
-{ GPIO_BASE, GPIO_IN,  GPIO_ALT1, GPIO_OUT_NO_CHG }, /* GPIO18	IRQ1	    PCI INTB	*/	\
-{ GPIO_BASE, GPIO_IN,  GPIO_ALT1, GPIO_OUT_NO_CHG }, /* GPIO19	IRQ2	    PCI INTC	*/	\
-{ GPIO_BASE, GPIO_IN,  GPIO_ALT1, GPIO_OUT_NO_CHG }, /* GPIO20	IRQ3	    PCI INTD	*/	\
-{ GPIO_BASE, GPIO_IN,  GPIO_ALT1, GPIO_OUT_NO_CHG }, /* GPIO21	IRQ4	    USB		*/	\
-{ GPIO_BASE, GPIO_IN,  GPIO_ALT1, GPIO_OUT_NO_CHG }, /* GPIO22	IRQ5	    EBC		*/	\
-{ GPIO_BASE, GPIO_OUT, GPIO_SEL,  GPIO_OUT_NO_CHG }, /* GPIO23	IRQ6	    unused	*/	\
-{ GPIO_BASE, GPIO_IN,  GPIO_ALT1, GPIO_OUT_NO_CHG }, /* GPIO24	UART0_DCD   UART1	*/	\
-{ GPIO_BASE, GPIO_IN,  GPIO_ALT1, GPIO_OUT_NO_CHG }, /* GPIO25	UART0_DSR		*/	\
-{ GPIO_BASE, GPIO_IN,  GPIO_ALT1, GPIO_OUT_NO_CHG }, /* GPIO26	UART0_RI		*/	\
-{ GPIO_BASE, GPIO_OUT, GPIO_ALT1, GPIO_OUT_NO_CHG }, /* GPIO27	UART0_DTR		*/	\
-{ GPIO_BASE, GPIO_IN,  GPIO_ALT1, GPIO_OUT_NO_CHG }, /* GPIO28	UART1_Rx    UART0	*/	\
-{ GPIO_BASE, GPIO_OUT, GPIO_ALT1, GPIO_OUT_NO_CHG }, /* GPIO29	UART1_Tx		*/	\
-{ GPIO_BASE, GPIO_OUT, GPIO_SEL,  GPIO_OUT_NO_CHG }, /* GPIO30	RejectPkt0  User LED1	*/	\
-{ GPIO_BASE, GPIO_OUT, GPIO_SEL,  GPIO_OUT_NO_CHG }, /* GPIO31	RejectPkt1  User LED2	*/	\
-}												\
-}
-
-/*
- * Init Memory Controller:
- *
- * BR0/1 and OR0/1 (FLASH)
- */
-
-#define FLASH_BASE0_PRELIM CONFIG_SYS_FLASH_BASE /* FLASH bank #0 */
-#define FLASH_BASE1_PRELIM  0xFC000000	/* FLASH bank #1 */
-
-/*-----------------------------------------------------------------------
- * Definitions for initial stack pointer and data area (in data cache)
- */
-/* use on chip memory (OCM) for temperary stack until sdram is tested */
-#define CONFIG_SYS_TEMP_STACK_OCM        1
-
-/* On Chip Memory location */
-#define CONFIG_SYS_OCM_DATA_ADDR	0xF8000000
-#define CONFIG_SYS_OCM_DATA_SIZE	0x1000
-#define CONFIG_SYS_INIT_RAM_ADDR	CONFIG_SYS_OCM_DATA_ADDR /* inside of SDRAM		*/
-#define CONFIG_SYS_INIT_RAM_SIZE	CONFIG_SYS_OCM_DATA_SIZE /* Size of used area in RAM	*/
-
-#define CONFIG_SYS_GBL_DATA_OFFSET    (CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE)
-#define CONFIG_SYS_INIT_SP_OFFSET      CONFIG_SYS_GBL_DATA_OFFSET
-
-/*-----------------------------------------------------------------------
- * External Bus Controller (EBC) Setup
- */
-
-/* Memory Bank 0 (Flash/SRAM) initialization */
-#define CONFIG_SYS_EBC_PB0AP           0x03815600
-#define CONFIG_SYS_EBC_PB0CR           0xFFE3A000  /* BAS=0xFFE,BS=2MB,BU=R/W,BW=16bit */
-
-/* Memory Bank 1 (NVRAM/RTC) initialization */
-#define CONFIG_SYS_EBC_PB1AP           0x05815600
-#define CONFIG_SYS_EBC_PB1CR           0xFC0BA000  /* BAS=0xFc0,BS=32MB,BU=R/W,BW=16bit */
-
-/* Memory Bank 2 (USB device) initialization */
-#define CONFIG_SYS_EBC_PB2AP           0x03016600
-#define CONFIG_SYS_EBC_PB2CR           0x50018000 /* BAS=0x500,BS=1MB,BU=R/W,BW=8bit */
-
-/* Memory Bank 3 (LCM and D-flip-flop) initialization */
-#define CONFIG_SYS_EBC_PB3AP           0x158FF600
-#define CONFIG_SYS_EBC_PB3CR           0x50118000 /* BAS=0x501,BS=1MB,BU=R/W,BW=8bit */
-
-/* Memory Bank 4 (not install) initialization */
-#define CONFIG_SYS_EBC_PB4AP           0x158FF600
-#define CONFIG_SYS_EBC_PB4CR           0x5021A000
-
-#define CPLD_REG0_ADDR	0x50100000
-#define CPLD_REG1_ADDR	0x50100001
-
-#endif	/* __CONFIG_H */
diff --git a/include/configs/taishan.h b/include/configs/taishan.h
deleted file mode 100644
index 3d5c351..0000000
--- a/include/configs/taishan.h
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * (C) Copyright 2007
- * Stefan Roese, DENX Software Engineering, sr@denx.de.
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-/************************************************************************
- * TAISHAN.h - configuration for AMCC 440GX Ref
- ***********************************************************************/
-
-#ifndef __CONFIG_H
-#define __CONFIG_H
-
-/*-----------------------------------------------------------------------
- * High Level Configuration Options
- *----------------------------------------------------------------------*/
-#define CONFIG_TAISHAN		1	/* Board is taishan		*/
-#define CONFIG_440GX		1	/* Specifc GX support		*/
-#define CONFIG_440		1	/* ... PPC440 family		*/
-#define CONFIG_SYS_CLK_FREQ	33333333 /* external freq to pll	*/
-
-#define	CONFIG_SYS_TEXT_BASE	0xFFFC0000
-
-/*
- * Include common defines/options for all AMCC eval boards
- */
-#define CONFIG_HOSTNAME		taishan
-#define CONFIG_USE_TTY		ttyS1
-#include "amcc-common.h"
-
-#define CONFIG_BOARD_EARLY_INIT_F 1	/* Call board_pre_init		*/
-#define CONFIG_MISC_INIT_R	1	/* Call misc_init_r		*/
-
-/*-----------------------------------------------------------------------
- * Base addresses -- Note these are effective addresses where the
- * actual resources get mapped (not physical addresses)
- *----------------------------------------------------------------------*/
-#define CONFIG_SYS_FLASH_BASE		0xfc000000	/* start of FLASH	*/
-#define CONFIG_SYS_PCI_MEMBASE		0x80000000	/* mapped pci memory	*/
-#define CONFIG_SYS_ISRAM_BASE		0xc0000000	/* internal SRAM	*/
-#define CONFIG_SYS_PCI_BASE		0xd0000000	/* internal PCI regs	*/
-
-#define CONFIG_SYS_EBC0_FLASH_BASE	CONFIG_SYS_FLASH_BASE
-#define CONFIG_SYS_EBC1_FPGA_BASE	(CONFIG_SYS_PERIPHERAL_BASE + 0x01000000)
-#define CONFIG_SYS_EBC2_LCM_BASE	(CONFIG_SYS_PERIPHERAL_BASE + 0x02000000)
-#define CONFIG_SYS_EBC3_CONN_BASE	(CONFIG_SYS_PERIPHERAL_BASE + 0x08000000)
-
-#define CONFIG_SYS_GPIO_BASE		(CONFIG_SYS_PERIPHERAL_BASE + 0x00000700)
-
-/*-----------------------------------------------------------------------
- * Initial RAM & stack pointer (placed in internal SRAM)
- *----------------------------------------------------------------------*/
-#define CONFIG_SYS_TEMP_STACK_OCM	1
-#define CONFIG_SYS_OCM_DATA_ADDR	CONFIG_SYS_ISRAM_BASE
-#define CONFIG_SYS_INIT_RAM_ADDR	CONFIG_SYS_ISRAM_BASE  /* Initial RAM address	*/
-#define CONFIG_SYS_INIT_RAM_SIZE	0x2000		/* Size of used area in RAM*/
-
-#define CONFIG_SYS_GBL_DATA_OFFSET	(CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE)
-#define CONFIG_SYS_INIT_SP_OFFSET	(CONFIG_SYS_GBL_DATA_OFFSET - 0x4)
-
-/*-----------------------------------------------------------------------
- * Serial Port
- *----------------------------------------------------------------------*/
-#define CONFIG_CONS_INDEX	2	/* Use UART1			*/
-#define CONFIG_SYS_EXT_SERIAL_CLOCK	(1843200 * 6)	/* Ext clk @ 11.059 MHz */
-
-/*-----------------------------------------------------------------------
- * Environment
- *----------------------------------------------------------------------*/
-#define CONFIG_ENV_IS_IN_FLASH     1	/* use FLASH for environment vars	*/
-
-/*-----------------------------------------------------------------------
- * FLASH related
- *----------------------------------------------------------------------*/
-#define CONFIG_SYS_FLASH_CFI
-#define CONFIG_FLASH_CFI_DRIVER
-#define CONFIG_SYS_FLASH_EMPTY_INFO		/* print 'E' for empty sector on flinfo */
-#define CONFIG_SYS_FLASH_USE_BUFFER_WRITE 1	/* use buffered writes (20x faster)	*/
-
-#define CONFIG_SYS_FLASH_BANKS_LIST    {CONFIG_SYS_FLASH_BASE}
-#define CONFIG_SYS_MAX_FLASH_BANKS     1		    /* number of banks	    */
-#define CONFIG_SYS_MAX_FLASH_SECT	1024		    /* sectors per device   */
-
-#undef	CONFIG_SYS_FLASH_CHECKSUM
-#define CONFIG_SYS_FLASH_ERASE_TOUT	120000	/* Timeout for Flash Erase (in ms)	*/
-#define CONFIG_SYS_FLASH_WRITE_TOUT	500	/* Timeout for Flash Write (in ms)	*/
-
-#define CONFIG_ENV_SECT_SIZE	0x40000 /* size of one complete sector	*/
-#define CONFIG_ENV_ADDR		(CONFIG_SYS_MONITOR_BASE-CONFIG_ENV_SECT_SIZE)
-#define	CONFIG_ENV_SIZE		0x4000	/* Total Size of Environment Sector	*/
-
-/* Address and size of Redundant Environment Sector	*/
-#define CONFIG_ENV_ADDR_REDUND	(CONFIG_ENV_ADDR-CONFIG_ENV_SECT_SIZE)
-#define CONFIG_ENV_SIZE_REDUND	(CONFIG_ENV_SIZE)
-
-/*-----------------------------------------------------------------------
- * E2PROM bootstrap configure value
- *----------------------------------------------------------------------*/
-
-/*
- * 800/133/66
- * IIC 0~15: 86 78 11 6a 61 A7 04 62 00 00 00 00 00 00 00 00
- */
-
-/*
- * 800/160/80
- * IIC 0~15: 86 78 c1 a6 09 67 04 63 00 00 00 00 00 00 00 00
- */
-
-/*-----------------------------------------------------------------------
- * DDR SDRAM
- *----------------------------------------------------------------------*/
-#undef CONFIG_SPD_EEPROM		/* Don't use SPD EEPROM for setup	*/
-#define CONFIG_SDRAM_BANK0	1	/* init onboard DDR SDRAM bank 0	*/
-#define	CONFIG_SYS_SDRAM0_TR0		0xC10A401A
-#undef CONFIG_SDRAM_ECC			/* enable ECC support			*/
-
-/*-----------------------------------------------------------------------
- * I2C
- *----------------------------------------------------------------------*/
-#define CONFIG_SYS_I2C_PPC4XX_SPEED_0		400000
-
-#undef CONFIG_SYS_I2C_MULTI_EEPROMS
-#define CONFIG_SYS_I2C_EEPROM_ADDR	0x50
-#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 1
-#define CONFIG_SYS_EEPROM_PAGE_WRITE_BITS 3
-#define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS 10
-
-#define CONFIG_SYS_BOOTSTRAP_IIC_ADDR	0x50
-
-/* I2C SYSMON (LM75, AD7414 is almost compatible)			*/
-#define CONFIG_DTT_LM75		1		/* ON Semi's LM75	*/
-#define CONFIG_DTT_SENSORS	{0}		/* Sensor addresses	*/
-#define CONFIG_SYS_DTT_MAX_TEMP	70
-#define CONFIG_SYS_DTT_LOW_TEMP	-30
-#define CONFIG_SYS_DTT_HYSTERESIS	3
-
-/*
- * Default environment variables
- */
-#define	CONFIG_EXTRA_ENV_SETTINGS					\
-	CONFIG_AMCC_DEF_ENV						\
-	CONFIG_AMCC_DEF_ENV_POWERPC					\
-	CONFIG_AMCC_DEF_ENV_PPC_OLD					\
-	CONFIG_AMCC_DEF_ENV_NOR_UPD					\
-	"kernel_addr=fc000000\0"					\
-	"ramdisk_addr=fc180000\0"					\
-	"kozio=bootm 0xffe00000\0"					\
-	""
-
-/*-----------------------------------------------------------------------
- * Networking
- *----------------------------------------------------------------------*/
-#define CONFIG_EMAC_NR_START	2	/* start with EMAC 2 (skip 0&1)	*/
-#define CONFIG_PHY_ADDR		0xff	     /* no phy on EMAC0		*/
-#define CONFIG_PHY1_ADDR	0xff	     /* no phy on EMAC1		*/
-#define CONFIG_PHY2_ADDR	0x1
-#define CONFIG_PHY3_ADDR	0x3
-#define CONFIG_ET1011C_PHY	1
-#define CONFIG_HAS_ETH0
-#define CONFIG_HAS_ETH1
-#define CONFIG_HAS_ETH2
-#define CONFIG_HAS_ETH3
-#define CONFIG_PHY_GIGE		1	/* Include GbE speed/duplex detection */
-#define CONFIG_PHY_RESET        1       /* reset phy upon startup         */
-#define CONFIG_PHY_RESET_DELAY	1000
-
-/*
- * Commands additional to the ones defined in amcc-common.h
- */
-#define CONFIG_CMD_DTT
-#define CONFIG_CMD_PCI
-
-/*-----------------------------------------------------------------------
- * PCI stuff
- *-----------------------------------------------------------------------
- */
-/* General PCI */
-#define CONFIG_PCI			/* include pci support		*/
-#define CONFIG_PCI_INDIRECT_BRIDGE	/* indirect PCI bridge support */
-#define CONFIG_PCI_PNP			/* do pci plug-and-play		*/
-#define CONFIG_EEPRO100       1		/* include PCI EEPRO100		*/
-#define CONFIG_PCI_SCAN_SHOW		/* show pci devices on startup	*/
-#define CONFIG_SYS_PCI_TARGBASE    0x80000000	/* PCIaddr mapped to CONFIG_SYS_PCI_MEMBASE */
-
-/* Board-specific PCI */
-#define CONFIG_SYS_PCI_TARGET_INIT		/* let board init pci target    */
-
-#define CONFIG_SYS_PCI_SUBSYS_VENDORID 0x10e8	/* AMCC */
-#define CONFIG_SYS_PCI_SUBSYS_DEVICEID 0xcafe	/* Whatever */
-
-#endif	/* __CONFIG_H */
diff --git a/include/configs/zynq-common.h b/include/configs/zynq-common.h
index 66b1e69..ca5ef04 100644
--- a/include/configs/zynq-common.h
+++ b/include/configs/zynq-common.h
@@ -72,6 +72,17 @@
 # define CONFIG_CMD_SF
 #endif
 
+/* QSPI */
+#ifdef CONFIG_ZYNQ_QSPI
+# define CONFIG_SF_DEFAULT_SPEED	30000000
+# define CONFIG_SPI_FLASH_ISSI
+# define CONFIG_SPI_FLASH_SPANSION
+# define CONFIG_SPI_FLASH_STMICRO
+# define CONFIG_SPI_FLASH_WINBOND
+# define CONFIG_SPI_FLASH_BAR
+# define CONFIG_CMD_SF
+#endif
+
 /* NOR */
 #ifndef CONFIG_SYS_NO_FLASH
 # define CONFIG_SYS_FLASH_BASE		0xE2000000
@@ -344,6 +355,10 @@
 #define CONFIG_SPL_SPI_LOAD
 #define CONFIG_SPL_SPI_FLASH_SUPPORT
 #define CONFIG_SYS_SPI_U_BOOT_OFFS	0x100000
+#define CONFIG_SYS_SPI_ARGS_OFFS	0x200000
+#define CONFIG_SYS_SPI_ARGS_SIZE	0x80000
+#define CONFIG_SYS_SPI_KERNEL_OFFS	(CONFIG_SYS_SPI_ARGS_OFFS + \
+					CONFIG_SYS_SPI_ARGS_SIZE)
 #endif
 
 /* for booting directly linux */
diff --git a/include/dm/device.h b/include/dm/device.h
index 8519612..28ba4ca 100644
--- a/include/dm/device.h
+++ b/include/dm/device.h
@@ -21,13 +21,13 @@
 struct driver_info;
 
 /* Driver is active (probed). Cleared when it is removed */
-#define DM_FLAG_ACTIVATED	(1 << 0)
+#define DM_FLAG_ACTIVATED		(1 << 0)
 
 /* DM is responsible for allocating and freeing platdata */
-#define DM_FLAG_ALLOC_PDATA	(1 << 1)
+#define DM_FLAG_ALLOC_PDATA		(1 << 1)
 
 /* DM should init this device prior to relocation */
-#define DM_FLAG_PRE_RELOC	(1 << 2)
+#define DM_FLAG_PRE_RELOC		(1 << 2)
 
 /* DM is responsible for allocating and freeing parent_platdata */
 #define DM_FLAG_ALLOC_PARENT_PDATA	(1 << 3)
@@ -36,10 +36,10 @@
 #define DM_FLAG_ALLOC_UCLASS_PDATA	(1 << 4)
 
 /* Allocate driver private data on a DMA boundary */
-#define DM_FLAG_ALLOC_PRIV_DMA	(1 << 5)
+#define DM_FLAG_ALLOC_PRIV_DMA		(1 << 5)
 
 /* Device is bound */
-#define DM_FLAG_BOUND	(1 << 6)
+#define DM_FLAG_BOUND			(1 << 6)
 
 /**
  * struct udevice - An instance of a driver
@@ -78,6 +78,10 @@
  * @req_seq: Requested sequence number for this device (-1 = any)
  * @seq: Allocated sequence number for this device (-1 = none). This is set up
  * when the device is probed and will be unique within the device's uclass.
+ * @devres_head: List of memory allocations associated with this device.
+ *		When CONFIG_DEVRES is enabled, devm_kmalloc() and friends will
+ *		add to this list. Memory so-allocated will be freed
+ *		automatically when the device is removed / unbound
  */
 struct udevice {
 	const struct driver *driver;
@@ -166,10 +170,6 @@
  * @per_child_auto_alloc_size: Each device can hold private data owned by
  * its parent. If required this will be automatically allocated if this
  * value is non-zero.
- * TODO(sjg@chromium.org): I'm considering dropping this, and just having
- * device_probe_child() pass it in. So far the use case for allocating it
- * is SPI, but I found that unsatisfactory. Since it is here I will leave it
- * until things are clearer.
  * @per_child_platdata_auto_alloc_size: A bus likes to store information about
  * its children. If non-zero this is the size of this data, to be allocated
  * in the child's parent_platdata pointer.
@@ -233,20 +233,6 @@
 void *dev_get_uclass_platdata(struct udevice *dev);
 
 /**
- * dev_get_parentdata() - Get the parent data for a device
- *
- * The parent data is data stored in the device but owned by the parent.
- * For example, a USB device may have parent data which contains information
- * about how to talk to the device over USB.
- *
- * This checks that dev is not NULL, but no other checks for now
- *
- * @dev		Device to check
- * @return parent data, or NULL if none
- */
-void *dev_get_parentdata(struct udevice *dev);
-
-/**
  * dev_get_priv() - Get the private data for a device
  *
  * This checks that dev is not NULL, but no other checks for now
@@ -257,12 +243,18 @@
 void *dev_get_priv(struct udevice *dev);
 
 /**
- * struct dev_get_parent() - Get the parent of a device
+ * dev_get_parent_priv() - Get the parent private data for a device
  *
- * @child:	Child to check
- * @return parent of child, or NULL if this is the root device
+ * The parent private data is data stored in the device but owned by the
+ * parent. For example, a USB device may have parent data which contains
+ * information about how to talk to the device over USB.
+ *
+ * This checks that dev is not NULL, but no other checks for now
+ *
+ * @dev		Device to check
+ * @return parent data, or NULL if none
  */
-struct udevice *dev_get_parent(struct udevice *child);
+void *dev_get_parent_priv(struct udevice *dev);
 
 /**
  * dev_get_uclass_priv() - Get the private uclass data for a device
@@ -275,16 +267,37 @@
 void *dev_get_uclass_priv(struct udevice *dev);
 
 /**
+ * struct dev_get_parent() - Get the parent of a device
+ *
+ * @child:	Child to check
+ * @return parent of child, or NULL if this is the root device
+ */
+struct udevice *dev_get_parent(struct udevice *child);
+
+/**
  * dev_get_driver_data() - get the driver data used to bind a device
  *
  * When a device is bound using a device tree node, it matches a
- * particular compatible string as in struct udevice_id. This function
+ * particular compatible string in struct udevice_id. This function
  * returns the associated data value for that compatible string. This is
  * the 'data' field in struct udevice_id.
  *
+ * As an example, consider this structure:
+ * static const struct udevice_id tegra_i2c_ids[] = {
+ *	{ .compatible = "nvidia,tegra114-i2c", .data = TYPE_114 },
+ *	{ .compatible = "nvidia,tegra20-i2c", .data = TYPE_STD },
+ *	{ .compatible = "nvidia,tegra20-i2c-dvc", .data = TYPE_DVC },
+ *	{ }
+ * };
+ *
+ * When driver model finds a driver for this it will store the 'data' value
+ * corresponding to the compatible string it matches. This function returns
+ * that value. This allows the driver to handle several variants of a device.
+ *
  * For USB devices, this is the driver_info field in struct usb_device_id.
  *
  * @dev:	Device to check
+ * @return driver data (0 if none is provided)
  */
 ulong dev_get_driver_data(struct udevice *dev);
 
@@ -299,7 +312,7 @@
  */
 const void *dev_get_driver_ops(struct udevice *dev);
 
-/*
+/**
  * device_get_uclass_id() - return the uclass ID of a device
  *
  * @dev:	Device to check
@@ -307,7 +320,7 @@
  */
 enum uclass_id device_get_uclass_id(struct udevice *dev);
 
-/*
+/**
  * dev_get_uclass_name() - return the uclass name of a device
  *
  * This checks that dev is not NULL.
@@ -512,7 +525,7 @@
 #endif
 
 /**
- * devres_alloc - Allocate device resource data
+ * devres_alloc() - Allocate device resource data
  * @release: Release function devres will be associated with
  * @size: Allocation size
  * @gfp: Allocation flags
@@ -528,7 +541,7 @@
 	_devres_alloc(release, size, gfp | __GFP_ZERO)
 
 /**
- * devres_free - Free device resource data
+ * devres_free() - Free device resource data
  * @res: Pointer to devres data to free
  *
  * Free devres created with devres_alloc().
@@ -536,7 +549,7 @@
 void devres_free(void *res);
 
 /**
- * devres_add - Register device resource
+ * devres_add() - Register device resource
  * @dev: Device to add resource to
  * @res: Resource to register
  *
@@ -547,7 +560,7 @@
 void devres_add(struct udevice *dev, void *res);
 
 /**
- * devres_find - Find device resource
+ * devres_find() - Find device resource
  * @dev: Device to lookup resource from
  * @release: Look for resources associated with this release function
  * @match: Match function (optional)
@@ -557,14 +570,13 @@
  * and for which @match returns 1.  If @match is NULL, it's considered
  * to match all.
  *
- * RETURNS:
- * Pointer to found devres, NULL if not found.
+ * @return pointer to found devres, NULL if not found.
  */
 void *devres_find(struct udevice *dev, dr_release_t release,
 		  dr_match_t match, void *match_data);
 
 /**
- * devres_get - Find devres, if non-existent, add one atomically
+ * devres_get() - Find devres, if non-existent, add one atomically
  * @dev: Device to lookup or add devres for
  * @new_res: Pointer to new initialized devres to add if not found
  * @match: Match function (optional)
@@ -574,14 +586,13 @@
  * as @new_res and for which @match return 1.  If found, @new_res is
  * freed; otherwise, @new_res is added atomically.
  *
- * RETURNS:
- * Pointer to found or added devres.
+ * @return ointer to found or added devres.
  */
 void *devres_get(struct udevice *dev, void *new_res,
 		 dr_match_t match, void *match_data);
 
 /**
- * devres_remove - Find a device resource and remove it
+ * devres_remove() - Find a device resource and remove it
  * @dev: Device to find resource from
  * @release: Look for resources associated with this release function
  * @match: Match function (optional)
@@ -592,14 +603,13 @@
  * match all.  If found, the resource is removed atomically and
  * returned.
  *
- * RETURNS:
- * Pointer to removed devres on success, NULL if not found.
+ * @return ointer to removed devres on success, NULL if not found.
  */
 void *devres_remove(struct udevice *dev, dr_release_t release,
 		    dr_match_t match, void *match_data);
 
 /**
- * devres_destroy - Find a device resource and destroy it
+ * devres_destroy() - Find a device resource and destroy it
  * @dev: Device to find resource from
  * @release: Look for resources associated with this release function
  * @match: Match function (optional)
@@ -613,14 +623,13 @@
  * only the devres-allocated data will be freed.  The caller becomes
  * responsible for freeing any other data.
  *
- * RETURNS:
- * 0 if devres is found and freed, -ENOENT if not found.
+ * @return 0 if devres is found and freed, -ENOENT if not found.
  */
 int devres_destroy(struct udevice *dev, dr_release_t release,
 		   dr_match_t match, void *match_data);
 
 /**
- * devres_release - Find a device resource and destroy it, calling release
+ * devres_release() - Find a device resource and destroy it, calling release
  * @dev: Device to find resource from
  * @release: Look for resources associated with this release function
  * @match: Match function (optional)
@@ -631,15 +640,14 @@
  * match all.  If found, the resource is removed atomically, the
  * release function called and the resource freed.
  *
- * RETURNS:
- * 0 if devres is found and freed, -ENOENT if not found.
+ * @return 0 if devres is found and freed, -ENOENT if not found.
  */
 int devres_release(struct udevice *dev, dr_release_t release,
 		   dr_match_t match, void *match_data);
 
 /* managed devm_k.alloc/kfree for device drivers */
 /**
- * devm_kmalloc - Resource-managed kmalloc
+ * devm_kmalloc() - Resource-managed kmalloc
  * @dev: Device to allocate memory for
  * @size: Allocation size
  * @gfp: Allocation gfp flags
@@ -648,8 +656,7 @@
  * automatically freed on driver detach.  Like all other devres
  * resources, guaranteed alignment is unsigned long long.
  *
- * RETURNS:
- * Pointer to allocated memory on success, NULL on failure.
+ * @return pointer to allocated memory on success, NULL on failure.
  */
 void *devm_kmalloc(struct udevice *dev, size_t size, gfp_t gfp);
 static inline void *devm_kzalloc(struct udevice *dev, size_t size, gfp_t gfp)
@@ -670,13 +677,13 @@
 }
 
 /**
- * devm_kfree - Resource-managed kfree
+ * devm_kfree() - Resource-managed kfree
  * @dev: Device this memory belongs to
- * @p: Memory to free
+ * @ptr: Memory to free
  *
  * Free memory allocated with devm_kmalloc().
  */
-void devm_kfree(struct udevice *dev, void *p);
+void devm_kfree(struct udevice *dev, void *ptr);
 
 #else /* ! CONFIG_DEVRES */
 
@@ -750,9 +757,9 @@
 	return kmalloc(n * size, flags | __GFP_ZERO);
 }
 
-static inline void devm_kfree(struct udevice *dev, void *p)
+static inline void devm_kfree(struct udevice *dev, void *ptr)
 {
-	kfree(p);
+	kfree(ptr);
 }
 
 #endif /* ! CONFIG_DEVRES */
diff --git a/include/linux/compat.h b/include/linux/compat.h
index fbebf91..59937de 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -4,6 +4,7 @@
 #include <malloc.h>
 #include <linux/types.h>
 #include <linux/err.h>
+#include <linux/kernel.h>
 
 struct unused {};
 typedef struct unused unused_t;
@@ -49,22 +50,47 @@
 {
 	return kmalloc(size, flags | __GFP_ZERO);
 }
+
+static inline void *kmalloc_array(size_t n, size_t size, gfp_t flags)
+{
+	if (size != 0 && n > SIZE_MAX / size)
+		return NULL;
+	return kmalloc(n * size, flags | __GFP_ZERO);
+}
+
+static inline void *kcalloc(size_t n, size_t size, gfp_t flags)
+{
+	return kmalloc_array(n, size, flags | __GFP_ZERO);
+}
+
 #define vmalloc(size)	kmalloc(size, 0)
 #define __vmalloc(size, flags, pgsz)	kmalloc(size, flags)
 static inline void *vzalloc(unsigned long size)
 {
 	return kzalloc(size, 0);
 }
-#define kfree(ptr)	free(ptr)
-#define vfree(ptr)	free(ptr)
+static inline void kfree(const void *block)
+{
+	free((void *)block);
+}
+static inline void vfree(const void *addr)
+{
+	free((void *)addr);
+}
 
 struct kmem_cache { int sz; };
 
 struct kmem_cache *get_mem(int element_sz);
 #define kmem_cache_create(a, sz, c, d, e)	get_mem(sz)
 void *kmem_cache_alloc(struct kmem_cache *obj, int flag);
-#define kmem_cache_free(obj, size)	free(size)
-#define kmem_cache_destroy(obj)		free(obj)
+static inline void kmem_cache_free(struct kmem_cache *cachep, void *obj)
+{
+	free(obj);
+}
+static inline void kmem_cache_destroy(struct kmem_cache *cachep)
+{
+	free(cachep);
+}
 
 #define DECLARE_WAITQUEUE(...)	do { } while (0)
 #define add_wait_queue(...)	do { } while (0)
@@ -159,6 +185,8 @@
 
 #define class_create(...)		__builtin_return_address(0)
 #define class_create_file(...)		0
+#define class_register(...)		0
+#define class_unregister(...)
 #define class_remove_file(...)
 #define class_destroy(...)
 #define misc_register(...)		0
@@ -171,6 +199,7 @@
 
 #define dev_set_name(...)		do { } while (0)
 #define device_register(...)		0
+#define device_unregister(...)
 #define volume_sysfs_init(...)		0
 #define volume_sysfs_close(...)		do { } while (0)
 
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index bc4d9bf..e3d3fc7 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -244,6 +244,7 @@
 #ifndef __UBOOT__
 	int (*_suspend) (struct mtd_info *mtd);
 	void (*_resume) (struct mtd_info *mtd);
+	void (*_reboot) (struct mtd_info *mtd);
 #endif
 	/*
 	 * If the driver is something smart, like UBI, it may need to maintain
@@ -478,6 +479,8 @@
 	return mtd_is_bitflip(err) || mtd_is_eccerr(err);
 }
 
+unsigned mtd_mmap_capabilities(struct mtd_info *mtd);
+
 #ifdef __UBOOT__
 /* drivers/mtd/mtdcore.h */
 int add_mtd_device(struct mtd_info *mtd);
diff --git a/include/linux/mtd/ubi.h b/include/linux/mtd/ubi.h
index 05d0ab5..036779b 100644
--- a/include/linux/mtd/ubi.h
+++ b/include/linux/mtd/ubi.h
@@ -12,6 +12,7 @@
 #include <linux/types.h>
 #ifndef __UBOOT__
 #include <linux/ioctl.h>
+#include <linux/scatterlist.h>
 #include <mtd/ubi-user.h>
 #endif
 
@@ -19,16 +20,25 @@
 #define UBI_ALL -1
 
 /*
+ * Maximum number of scatter gather list entries,
+ * we use only 64 to have a lower memory foot print.
+ */
+#define UBI_MAX_SG_COUNT 64
+
+/*
  * enum ubi_open_mode - UBI volume open mode constants.
  *
  * UBI_READONLY: read-only mode
  * UBI_READWRITE: read-write mode
  * UBI_EXCLUSIVE: exclusive mode
+ * UBI_METAONLY: modify only the volume meta-data,
+ *  i.e. the data stored in the volume table, but not in any of volume LEBs.
  */
 enum {
 	UBI_READONLY = 1,
 	UBI_READWRITE,
-	UBI_EXCLUSIVE
+	UBI_EXCLUSIVE,
+	UBI_METAONLY
 };
 
 /**
@@ -106,6 +116,37 @@
 };
 
 /**
+ * struct ubi_sgl - UBI scatter gather list data structure.
+ * @list_pos: current position in @sg[]
+ * @page_pos: current position in @sg[@list_pos]
+ * @sg: the scatter gather list itself
+ *
+ * ubi_sgl is a wrapper around a scatter list which keeps track of the
+ * current position in the list and the current list item such that
+ * it can be used across multiple ubi_leb_read_sg() calls.
+ */
+struct ubi_sgl {
+	int list_pos;
+	int page_pos;
+#ifndef __UBOOT__
+	struct scatterlist sg[UBI_MAX_SG_COUNT];
+#endif
+};
+
+/**
+ * ubi_sgl_init - initialize an UBI scatter gather list data structure.
+ * @usgl: the UBI scatter gather struct itself
+ *
+ * Please note that you still have to use sg_init_table() or any adequate
+ * function to initialize the unterlaying struct scatterlist.
+ */
+static inline void ubi_sgl_init(struct ubi_sgl *usgl)
+{
+	usgl->list_pos = 0;
+	usgl->page_pos = 0;
+}
+
+/**
  * struct ubi_device_info - UBI device description data structure.
  * @ubi_num: ubi device number
  * @leb_size: logical eraseblock size on this UBI device
@@ -214,6 +255,8 @@
 void ubi_close_volume(struct ubi_volume_desc *desc);
 int ubi_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset,
 		 int len, int check);
+int ubi_leb_read_sg(struct ubi_volume_desc *desc, int lnum, struct ubi_sgl *sgl,
+		   int offset, int len, int check);
 int ubi_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf,
 		  int offset, int len);
 int ubi_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf,
@@ -234,4 +277,14 @@
 {
 	return ubi_leb_read(desc, lnum, buf, offset, len, 0);
 }
+
+/*
+ * This function is the same as the 'ubi_leb_read_sg()' function, but it does
+ * not provide the checking capability.
+ */
+static inline int ubi_read_sg(struct ubi_volume_desc *desc, int lnum,
+			      struct ubi_sgl *sgl, int offset, int len)
+{
+	return ubi_leb_read_sg(desc, lnum, sgl, offset, len, 0);
+}
 #endif /* !__LINUX_UBI_H__ */
diff --git a/include/mtd/cfi_flash.h b/include/mtd/cfi_flash.h
index 048b477..52572b9 100644
--- a/include/mtd/cfi_flash.h
+++ b/include/mtd/cfi_flash.h
@@ -105,10 +105,10 @@
 #define NUM_ERASE_REGIONS	4 /* max. number of erase regions */
 
 typedef union {
-	unsigned char c;
-	unsigned short w;
-	unsigned long l;
-	unsigned long long ll;
+	u8 w8;
+	u16 w16;
+	u32 w32;
+	u64 w64;
 } cfiword_t;
 
 /* CFI standard query structure */
diff --git a/include/pci.h b/include/pci.h
index e24c970..ed135a5 100644
--- a/include/pci.h
+++ b/include/pci.h
@@ -797,7 +797,7 @@
  *
  * Every device on a PCI bus has this per-child data.
  *
- * It can be accessed using dev_get_parentdata(dev) if dev->parent is a
+ * It can be accessed using dev_get_parent_priv(dev) if dev->parent is a
  * PCI bus (i.e. UCLASS_PCI)
  *
  * @devfn:	Encoded device and function index - see PCI_DEVFN()
diff --git a/include/spi.h b/include/spi.h
index 51fdfd6..b4d2723 100644
--- a/include/spi.h
+++ b/include/spi.h
@@ -88,7 +88,7 @@
  * struct spi_slave - Representation of a SPI slave
  *
  * For driver model this is the per-child data used by the SPI bus. It can
- * be accessed using dev_get_parentdata() on the slave device. The SPI uclass
+ * be accessed using dev_get_parent_priv() on the slave device. The SPI uclass
  * sets uip per_child_auto_alloc_size to sizeof(struct spi_slave), and the
  * driver should not override it. Two platform data fields (max_hz and mode)
  * are copied into this structure to provide an initial value. This allows
diff --git a/include/spi_flash.h b/include/spi_flash.h
index 3b2d555..4312d3d 100644
--- a/include/spi_flash.h
+++ b/include/spi_flash.h
@@ -38,10 +38,10 @@
  *
  * @spi:		SPI slave
  * @dev:		SPI flash device
- * @flags:		Indication of spi flash flags
  * @name:		Name of SPI flash
  * @dual_flash:		Indicates dual flash memories - dual stacked, parallel
  * @shift:		Flash shift useful in dual parallel
+ * @flags:		Indication of spi flash flags
  * @size:		Total flash size
  * @page_size:		Write (page) size
  * @sector_size:	Sector size
@@ -49,7 +49,6 @@
  * @bank_read_cmd:	Bank read cmd
  * @bank_write_cmd:	Bank write cmd
  * @bank_curr:		Current flash bank
- * @poll_cmd:		Poll cmd - for flash erase/program
  * @erase_cmd:		Erase cmd 4K, 32K, 64K
  * @read_cmd:		Read cmd - Array Fast, Extn read and quad read.
  * @write_cmd:		Write cmd - page and quad program.
@@ -67,11 +66,11 @@
 	struct spi_slave *spi;
 #ifdef CONFIG_DM_SPI_FLASH
 	struct udevice *dev;
-	u16 flags;
 #endif
 	const char *name;
 	u8 dual_flash;
 	u8 shift;
+	u16 flags;
 
 	u32 size;
 	u32 page_size;
@@ -82,7 +81,6 @@
 	u8 bank_write_cmd;
 	u8 bank_curr;
 #endif
-	u8 poll_cmd;
 	u8 erase_cmd;
 	u8 read_cmd;
 	u8 write_cmd;
diff --git a/include/tis.h b/include/tis.h
deleted file mode 100644
index 1985d9e..0000000
--- a/include/tis.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2011 The Chromium OS Authors.
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#ifndef __TIS_H
-#define __TIS_H
-
-#ifndef CONFIG_DM_TPM
-
-#include <common.h>
-
-/* Low-level interface to access TPM */
-
-/*
- * tis_init()
- *
- * Initialize the TPM device. Returns 0 on success or -1 on
- * failure (in case device probing did not succeed).
- */
-int tis_init(void);
-
-/*
- * tis_open()
- *
- * Requests access to locality 0 for the caller. After all commands have been
- * completed the caller is supposed to call tis_close().
- *
- * Returns 0 on success, -1 on failure.
- */
-int tis_open(void);
-
-/*
- * tis_close()
- *
- * terminate the currect session with the TPM by releasing the locked
- * locality. Returns 0 on success of -1 on failure (in case lock
- * removal did not succeed).
- */
-int tis_close(void);
-
-/*
- * tis_sendrecv()
- *
- * Send the requested data to the TPM and then try to get its response
- *
- * @sendbuf - buffer of the data to send
- * @send_size size of the data to send
- * @recvbuf - memory to save the response to
- * @recv_len - pointer to the size of the response buffer
- *
- * Returns 0 on success (and places the number of response bytes at recv_len)
- * or -1 on failure.
- */
-int tis_sendrecv(const uint8_t *sendbuf, size_t send_size, uint8_t *recvbuf,
-			size_t *recv_len);
-#endif
-
-#endif /* __TIS_H */
diff --git a/include/tpm.h b/include/tpm.h
index 086b672..9a6585d 100644
--- a/include/tpm.h
+++ b/include/tpm.h
@@ -8,8 +8,6 @@
 #ifndef __TPM_H
 #define __TPM_H
 
-#include <tis.h>
-
 /*
  * Here is a partial implementation of TPM commands.  Please consult TCG Main
  * Specification for definitions of TPM commands.
@@ -196,8 +194,6 @@
 	u8	disable_full_da_logic_info;
 } __packed;
 
-#ifdef CONFIG_DM_TPM
-
 /* Max buffer size supported by our tpm */
 #define TPM_DEV_BUFSIZE		1260
 
@@ -375,8 +371,6 @@
 int tpm_xfer(struct udevice *dev, const uint8_t *sendbuf, size_t send_size,
 	     uint8_t *recvbuf, size_t *recv_size);
 
-#endif /* CONFIG_DM_TPM */
-
 /**
  * Initialize TPM device.  It must be called before any TPM commands.
  *
diff --git a/include/usb.h b/include/usb.h
index 88ebbe6..3d0facb 100644
--- a/include/usb.h
+++ b/include/usb.h
@@ -96,7 +96,7 @@
  * (the hubs) have this as parent data. Hubs are children of controllers or
  * other hubs and there is always a single root hub for each controller.
  * Therefore struct usb_device can always be accessed with
- * dev_get_parentdata(dev), where dev is a USB device.
+ * dev_get_parent_priv(dev), where dev is a USB device.
  *
  * Pointers exist for obtaining both the device (could be any uclass) and
  * controller (UCLASS_USB) from this structure. The controller does not have
diff --git a/lib/Kconfig b/lib/Kconfig
index a8f8460..30e84ed 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -56,6 +56,7 @@
 
 config TPM
 	bool "Trusted Platform Module (TPM) Support"
+	depends on DM
 	help
 	  This enables support for TPMs which can be used to provide security
 	  features for your board. The TPM can be connected via LPC or I2C
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index 1a86369..9db033a 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -219,13 +219,13 @@
 
 		for (i = 0; i < num; i++) {
 			debug("pci address #%d: %08lx %08lx %08lx\n", i,
-			      (ulong)fdt_addr_to_cpu(cell[0]),
-			      (ulong)fdt_addr_to_cpu(cell[1]),
-			      (ulong)fdt_addr_to_cpu(cell[2]));
-			if ((fdt_addr_to_cpu(*cell) & type) == type) {
-				addr->phys_hi = fdt_addr_to_cpu(cell[0]);
-				addr->phys_mid = fdt_addr_to_cpu(cell[1]);
-				addr->phys_lo = fdt_addr_to_cpu(cell[2]);
+			      (ulong)fdt32_to_cpu(cell[0]),
+			      (ulong)fdt32_to_cpu(cell[1]),
+			      (ulong)fdt32_to_cpu(cell[2]));
+			if ((fdt32_to_cpu(*cell) & type) == type) {
+				addr->phys_hi = fdt32_to_cpu(cell[0]);
+				addr->phys_mid = fdt32_to_cpu(cell[1]);
+				addr->phys_lo = fdt32_to_cpu(cell[1]);
 				break;
 			} else {
 				cell += (FDT_PCI_ADDR_CELLS +
diff --git a/lib/tpm.c b/lib/tpm.c
index 5d5f707..8a62216 100644
--- a/lib/tpm.c
+++ b/lib/tpm.c
@@ -7,7 +7,6 @@
 
 #include <common.h>
 #include <dm.h>
-#include <tis.h>
 #include <tpm.h>
 #include <asm/unaligned.h>
 #include <u-boot/sha1.h>
@@ -230,6 +229,8 @@
 static uint32_t tpm_sendrecv_command(const void *command,
 		void *response, size_t *size_ptr)
 {
+	struct udevice *dev;
+	int ret;
 	uint8_t response_buffer[COMMAND_BUFFER_SIZE];
 	size_t response_length;
 	uint32_t err;
@@ -240,19 +241,13 @@
 		response = response_buffer;
 		response_length = sizeof(response_buffer);
 	}
-#ifdef CONFIG_DM_TPM
-	struct udevice *dev;
-	int ret;
 
 	ret = uclass_first_device(UCLASS_TPM, &dev);
 	if (ret)
 		return ret;
 	err = tpm_xfer(dev, command, tpm_command_size(command),
 		       response, &response_length);
-#else
-	err = tis_sendrecv(command, tpm_command_size(command),
-			response, &response_length);
-#endif
+
 	if (err < 0)
 		return TPM_LIB_ERROR;
 	if (size_ptr)
@@ -264,21 +259,12 @@
 int tpm_init(void)
 {
 	int err;
-
-#ifdef CONFIG_DM_TPM
 	struct udevice *dev;
 
 	err = uclass_first_device(UCLASS_TPM, &dev);
 	if (err)
 		return err;
 	return tpm_open(dev);
-#else
-	err = tis_init();
-	if (err)
-		return err;
-
-	return tis_open();
-#endif
 }
 
 uint32_t tpm_startup(enum tpm_startup_type mode)
diff --git a/test/dm/bus.c b/test/dm/bus.c
index a215905..3b5a23b 100644
--- a/test/dm/bus.c
+++ b/test/dm/bus.c
@@ -46,7 +46,7 @@
 
 static int testbus_child_pre_probe(struct udevice *dev)
 {
-	struct dm_test_parent_data *parent_data = dev_get_parentdata(dev);
+	struct dm_test_parent_data *parent_data = dev_get_parent_priv(dev);
 
 	parent_data->flag += FLAG_CHILD_PROBED;
 
@@ -64,7 +64,7 @@
 
 static int testbus_child_post_remove(struct udevice *dev)
 {
-	struct dm_test_parent_data *parent_data = dev_get_parentdata(dev);
+	struct dm_test_parent_data *parent_data = dev_get_parent_priv(dev);
 	struct dm_test_state *dms = test_state;
 
 	parent_data->flag += FLAG_CHILD_REMOVED;
@@ -215,20 +215,20 @@
 
 	/* Check that parent data is allocated */
 	ut_assertok(device_find_child_by_seq(bus, 0, true, &dev));
-	ut_asserteq_ptr(NULL, dev_get_parentdata(dev));
+	ut_asserteq_ptr(NULL, dev_get_parent_priv(dev));
 	ut_assertok(device_get_child_by_seq(bus, 0, &dev));
-	parent_data = dev_get_parentdata(dev);
+	parent_data = dev_get_parent_priv(dev);
 	ut_assert(NULL != parent_data);
 
 	/* Check that it starts at 0 and goes away when device is removed */
 	parent_data->sum += 5;
 	ut_asserteq(5, parent_data->sum);
 	device_remove(dev);
-	ut_asserteq_ptr(NULL, dev_get_parentdata(dev));
+	ut_asserteq_ptr(NULL, dev_get_parent_priv(dev));
 
 	/* Check that we can do this twice */
 	ut_assertok(device_get_child_by_seq(bus, 0, &dev));
-	parent_data = dev_get_parentdata(dev);
+	parent_data = dev_get_parent_priv(dev);
 	ut_assert(NULL != parent_data);
 	parent_data->sum += 5;
 	ut_asserteq(5, parent_data->sum);
@@ -239,11 +239,11 @@
 	uclass_foreach_dev(dev, uc) {
 		/* Ignore these if they are not on this bus */
 		if (dev->parent != bus) {
-			ut_asserteq_ptr(NULL, dev_get_parentdata(dev));
+			ut_asserteq_ptr(NULL, dev_get_parent_priv(dev));
 			continue;
 		}
 		ut_assertok(device_probe(dev));
-		parent_data = dev_get_parentdata(dev);
+		parent_data = dev_get_parent_priv(dev);
 
 		parent_data->sum = value;
 		value += 5;
@@ -255,7 +255,7 @@
 		/* Ignore these if they are not on this bus */
 		if (dev->parent != bus)
 			continue;
-		parent_data = dev_get_parentdata(dev);
+		parent_data = dev_get_parent_priv(dev);
 
 		ut_asserteq(value, parent_data->sum);
 		value += 5;
@@ -311,10 +311,10 @@
 		/* Ignore these if they are not on this bus */
 		if (dev->parent != bus)
 			continue;
-		ut_asserteq_ptr(NULL, dev_get_parentdata(dev));
+		ut_asserteq_ptr(NULL, dev_get_parent_priv(dev));
 
 		ut_assertok(device_probe(dev));
-		parent_data = dev_get_parentdata(dev);
+		parent_data = dev_get_parent_priv(dev);
 		ut_asserteq(FLAG_CHILD_PROBED, parent_data->flag);
 	}
 
@@ -322,10 +322,10 @@
 		/* Ignore these if they are not on this bus */
 		if (dev->parent != bus)
 			continue;
-		parent_data = dev_get_parentdata(dev);
+		parent_data = dev_get_parent_priv(dev);
 		ut_asserteq(FLAG_CHILD_PROBED, parent_data->flag);
 		ut_assertok(device_remove(dev));
-		ut_asserteq_ptr(NULL, dev_get_parentdata(dev));
+		ut_asserteq_ptr(NULL, dev_get_parent_priv(dev));
 		ut_asserteq_ptr(dms->removed, dev);
 	}
 	test_state = NULL;