Merge branch 'master' of git://git.denx.de/u-boot-spi
diff --git a/arch/arm/cpu/armv7/omap5/hw_data.c b/arch/arm/cpu/armv7/omap5/hw_data.c
index fbbc486..a1b249e 100644
--- a/arch/arm/cpu/armv7/omap5/hw_data.c
+++ b/arch/arm/cpu/armv7/omap5/hw_data.c
@@ -170,7 +170,7 @@
 
 static const struct dpll_params per_dpll_params_768mhz_dra7xx[NUM_SYS_CLKS] = {
 	{32, 0, 4, 1, 3, 4, 10, 2, -1, -1, -1, -1},		/* 12 MHz   */
-	{96, 4, 4, 1, 3, 4, 10, 2, -1, -1, -1, -1},		/* 20 MHz   */
+	{96, 4, 4, 1, 3, 4, 4, 2, -1, -1, -1, -1},		/* 20 MHz   */
 	{160, 6, 4, 1, 3, 4, 10, 2, -1, -1, -1, -1},		/* 16.8 MHz */
 	{20, 0, 4, 1, 3, 4, 10, 2, -1, -1, -1, -1},		/* 19.2 MHz */
 	{192, 12, 4, 1, 3, 4, 10, 2, -1, -1, -1, -1},		/* 26 MHz   */
@@ -426,6 +426,10 @@
 #ifdef CONFIG_DRIVER_TI_CPSW
 		(*prcm)->cm_gmac_gmac_clkctrl,
 #endif
+
+#ifdef CONFIG_TI_QSPI
+		(*prcm)->cm_l4per_qspi_clkctrl,
+#endif
 		0
 	};
 
@@ -454,6 +458,10 @@
 			 clk_modules_explicit_en_essential,
 			 1);
 
+#ifdef CONFIG_TI_QSPI
+	setbits_le32((*prcm)->cm_l4per_qspi_clkctrl, (1<<24));
+#endif
+
 	/* Enable SCRM OPT clocks for PER and CORE dpll */
 	setbits_le32((*prcm)->cm_wkupaon_scrm_clkctrl,
 			OPTFCLKEN_SCRM_PER_MASK);
diff --git a/arch/arm/cpu/armv7/omap5/prcm-regs.c b/arch/arm/cpu/armv7/omap5/prcm-regs.c
index 5a3d52c..7a7cade 100644
--- a/arch/arm/cpu/armv7/omap5/prcm-regs.c
+++ b/arch/arm/cpu/armv7/omap5/prcm-regs.c
@@ -921,6 +921,7 @@
 	.cm_l4per_gpio8_clkctrl			= 0x4a009818,
 	.cm_l4per_mmcsd3_clkctrl		= 0x4a009820,
 	.cm_l4per_mmcsd4_clkctrl		= 0x4a009828,
+	.cm_l4per_qspi_clkctrl			= 0x4a009838,
 	.cm_l4per_uart1_clkctrl			= 0x4a009840,
 	.cm_l4per_uart2_clkctrl			= 0x4a009848,
 	.cm_l4per_uart3_clkctrl			= 0x4a009850,
diff --git a/arch/arm/include/asm/arch-exynos/spi.h b/arch/arm/include/asm/arch-exynos/spi.h
index fb23aa6..147c1a7 100644
--- a/arch/arm/include/asm/arch-exynos/spi.h
+++ b/arch/arm/include/asm/arch-exynos/spi.h
@@ -22,7 +22,7 @@
 	unsigned int		rx_data;	/* 0x1c */
 	unsigned int		pkt_cnt;	/* 0x20 */
 	unsigned char		reserved2[4];
-	unsigned char		reserved3[4];
+	unsigned int		swap_cfg;	/* 0x28 */
 	unsigned int		fb_clk;		/* 0x2c */
 	unsigned char		padding[0xffd0];
 };
@@ -62,5 +62,14 @@
 /* Packet Count */
 #define SPI_PACKET_CNT_EN	(1 << 16)
 
+/* Swap config */
+#define SPI_TX_SWAP_EN		(1 << 0)
+#define SPI_TX_BYTE_SWAP	(1 << 2)
+#define SPI_TX_HWORD_SWAP	(1 << 3)
+#define SPI_TX_BYTE_SWAP	(1 << 2)
+#define SPI_RX_SWAP_EN		(1 << 4)
+#define SPI_RX_BYTE_SWAP	(1 << 6)
+#define SPI_RX_HWORD_SWAP	(1 << 7)
+
 #endif /* __ASSEMBLY__ */
 #endif
diff --git a/arch/arm/include/asm/arch-omap5/omap.h b/arch/arm/include/asm/arch-omap5/omap.h
index e9a51d3..414d37a 100644
--- a/arch/arm/include/asm/arch-omap5/omap.h
+++ b/arch/arm/include/asm/arch-omap5/omap.h
@@ -61,6 +61,9 @@
 /* GPMC */
 #define OMAP54XX_GPMC_BASE	0x50000000
 
+/* QSPI */
+#define QSPI_BASE		0x4B300000
+
 /*
  * Hardware Register Details
  */
diff --git a/arch/arm/include/asm/arch-omap5/spl.h b/arch/arm/include/asm/arch-omap5/spl.h
index fe8b0c0..57f0de5 100644
--- a/arch/arm/include/asm/arch-omap5/spl.h
+++ b/arch/arm/include/asm/arch-omap5/spl.h
@@ -15,6 +15,7 @@
 #define BOOT_DEVICE_MMC1        5
 #define BOOT_DEVICE_MMC2        6
 #define BOOT_DEVICE_MMC2_2	7
+#define BOOT_DEVICE_SPI		10
 
 #define MMC_BOOT_DEVICES_START	BOOT_DEVICE_MMC1
 #define MMC_BOOT_DEVICES_END	BOOT_DEVICE_MMC2_2
diff --git a/arch/arm/include/asm/omap_common.h b/arch/arm/include/asm/omap_common.h
index 61fee9f..3a998cc 100644
--- a/arch/arm/include/asm/omap_common.h
+++ b/arch/arm/include/asm/omap_common.h
@@ -266,6 +266,7 @@
 	u32 cm_l4per_mmcsd4_clkctrl;
 	u32 cm_l4per_msprohg_clkctrl;
 	u32 cm_l4per_slimbus2_clkctrl;
+	u32 cm_l4per_qspi_clkctrl;
 	u32 cm_l4per_uart1_clkctrl;
 	u32 cm_l4per_uart2_clkctrl;
 	u32 cm_l4per_uart3_clkctrl;
diff --git a/board/ti/dra7xx/mux_data.h b/board/ti/dra7xx/mux_data.h
index 0a86594..6965cc5 100644
--- a/board/ti/dra7xx/mux_data.h
+++ b/board/ti/dra7xx/mux_data.h
@@ -51,5 +51,15 @@
 	{RGMII0_RXD2, (IEN | M0) },
 	{RGMII0_RXD1, (IEN | M0) },
 	{RGMII0_RXD0, (IEN | M0) },
+	{GPMC_A13, (IEN | PDIS | M1)},  /* QSPI1_RTCLK */
+	{GPMC_A14, (IEN | PDIS | M1)},  /* QSPI1_D[3] */
+	{GPMC_A15, (IEN | PDIS | M1)},  /* QSPI1_D[2] */
+	{GPMC_A16, (IEN | PDIS | M1)},  /* QSPI1_D[1] */
+	{GPMC_A17, (IEN | PDIS | M1)},  /* QSPI1_D[0] */
+	{GPMC_A18, (M1)},  /* QSPI1_SCLK */
+	{GPMC_A3, (IEN | PDIS | M1)},   /* QSPI1_CS2 */
+	{GPMC_A4, (IEN | PDIS | M1)},   /* QSPI1_CS3 */
+	{GPMC_CS2, (IEN | PTU | PDIS | M1)},    /* QSPI1_CS0 */
+	{GPMC_CS3, (IEN | PTU | PDIS | M1)},    /* QSPI1_CS1*/
 };
 #endif /* _MUX_DATA_DRA7XX_H_ */
diff --git a/doc/SPI/README.ti_qspi_dra_test b/doc/SPI/README.ti_qspi_dra_test
new file mode 100644
index 0000000..fe37857
--- /dev/null
+++ b/doc/SPI/README.ti_qspi_dra_test
@@ -0,0 +1,48 @@
+-------------------------------------------------
+   Simple steps used to test the QSPI at U-Boot
+-------------------------------------------------
+
+For #1, build the patched U-Boot and load MLO/u-boot.img
+
+----------------------------------
+Boot from another medium like MMC
+----------------------------------
+
+U-Boot# mmc dev 0
+mmc0 is current device
+U-Boot# fatload mmc 0 0x82000000 MLO
+reading MLO
+55872 bytes read in 8 ms (6.7 MiB/s)
+U-Boot# fatload mmc 0 0x83000000 u-boot.img
+reading u-boot.img
+248600 bytes read in 19 ms (12.5 MiB/s)
+
+--------------------------------------------------
+Commands to erase/write u-boot/mlo to flash device
+--------------------------------------------------
+U-Boot# sf probe 0
+SF: Detected S25FL256S_64K with page size 256 Bytes, erase size 64 KiB, total 32 MiB, mapped at 5c000000
+SF: Warning - Only lower 16MiB accessible, Full access #define CONFIG_SPI_FLASH_BAR
+U-Boot# sf erase 0 0x10000
+SF: 65536 bytes @ 0x0 Erased: OK
+U-Boot# sf erase 0x20000 0x10000
+SF: 65536 bytes @ 0x20000 Erased: OK
+U-Boot# sf erase 0x30000 0x10000
+SF: 65536 bytes @ 0x30000 Erased: OK
+U-Boot# sf erase 0x40000 0x10000
+SF: 65536 bytes @ 0x40000 Erased: OK
+U-Boot# sf erase 0x50000 0x10000
+SF: 65536 bytes @ 0x50000 Erased: OK
+U-Boot# sf erase 0x60000 0x10000
+SF: 65536 bytes @ 0x60000 Erased: OK
+U-Boot# sf write 82000000 0 0x10000
+SF: 65536 bytes @ 0x0 Written: OK
+U-Boot# sf write 83000000 0x20000 0x60000
+SF: 393216 bytes @ 0x20000 Written: OK
+
+For #2, set sysboot to QSPI-1 boot mode(SYSBOOT[5:0] = 100110) and power
+on. ROM should find the GP header at offset 0 and load/execute SPL. SPL
+then detects that ROM was in QSPI-1 mode (boot code 10) and attempts to
+find a U-Boot image header at offset 0x20000 (set in the config file)
+and proceeds to load that image using the U-Boot image payload offset/size
+from the header. It will then start U-Boot.
diff --git a/doc/SPI/README.ti_qspi_flash b/doc/SPI/README.ti_qspi_flash
new file mode 100644
index 0000000..1b86d01
--- /dev/null
+++ b/doc/SPI/README.ti_qspi_flash
@@ -0,0 +1,47 @@
+QSPI U-boot support
+------------------
+
+Host processor is connected to serial flash device via qpsi
+interface. QSPI is a kind of spi module that allows single,
+dual and quad read access to external spi devices. The module
+has a memory mapped interface which provide direct interface
+for accessing data form external spi devices.
+
+The one QSPI in the device is primarily intended for fast booting
+from Quad SPI flash devices.
+
+Usecase
+-------
+
+MLO/u-boot.img will be flashed from SD/MMC to the flash device
+using serial flash erase and write commands. Then, switch settings
+will be changed to qspi boot. Then, the ROM code will read MLO
+from the predefined location in the flash, where it was flashed and
+execute it after storing it in SDRAM. Then, the MLO will read
+u-boot.img from flash and execute it from SDRAM.
+
+SPI mode
+-------
+SPI mode uses mtd spi framework for transfer and reception of data.
+Can be used in:
+1. Normal mode: use single pin for transfers
+2. Dual Mode: use two pins for transfers.
+3. Quad mode: use four pin for transfer
+
+Memory mapped read mode
+-----------------------
+In this, SPI controller is configured using configuration port and then
+controler is switched to memory mapped port for data read.
+
+Driver
+------
+drivers/qspi/ti_qspi.c
+    - Newly created file which is responsible for configuring the
+	qspi controller and also for providing the low level api which
+	is responsible for transferring the datas from host controller
+	to flash device and vice versa.
+
+Testing
+-------
+A seperated file named README.dra_qspi_test has been created which gives all the
+details about the commands required to test qspi at u-boot level.
diff --git a/doc/SPI/status.txt b/doc/SPI/status.txt
new file mode 100644
index 0000000..62c3c85
--- /dev/null
+++ b/doc/SPI/status.txt
@@ -0,0 +1,31 @@
+Status on SPI subsystem:
+=======================
+
+SPI COMMAND (common/cmd_sf, cmd_spi):
+-
+
+SPI FLASH (drivers/mtd/spi):
+- sf_probe.c: SPI flash probing code.
+- sf_ops.c: SPI flash operations code.
+- sf.c: SPI flash interface, which interacts controller driver.
+- Bank Address Register (Accessing flashes > 16Mbytes in 3-byte addressing)
+- Added memory_mapped support for read operations.
+- Common probe support for all supported flash vendors except, ramtron.
+
+SPI DRIVERS (drivers/spi):
+-
+
+TODO:
+- Runtime detection of spi_flash params, SFDP(if possible)
+- Add support for multibus build/accessing.
+- Extended read commands support(dual read, dual IO read)
+- Quad Page Program support.
+- Quad Read support(quad fast read, quad IO read)
+- Dual flash connection topology support(accessing two spi flash memories with single cs)
+- Banking support on dual flash connection topology.
+- Need proper cleanups on spi_flash and drivers.
+
+--
+Jagannadha Sutradharudu Teki <jagannadh.teki@gmail.com>
+18-09-2013.
+07-10-2013.
diff --git a/drivers/mtd/spi/Makefile b/drivers/mtd/spi/Makefile
index 191138a..86ffc59 100644
--- a/drivers/mtd/spi/Makefile
+++ b/drivers/mtd/spi/Makefile
@@ -14,16 +14,11 @@
 COBJS-$(CONFIG_SPL_SPI_BOOT)	+= fsl_espi_spl.o
 endif
 
-COBJS-$(CONFIG_SPI_FLASH)	+= spi_flash.o
-COBJS-$(CONFIG_SPI_FLASH_ATMEL)	+= atmel.o
-COBJS-$(CONFIG_SPI_FLASH_EON)	+= eon.o
-COBJS-$(CONFIG_SPI_FLASH_GIGADEVICE)	+= gigadevice.o
-COBJS-$(CONFIG_SPI_FLASH_MACRONIX)	+= macronix.o
-COBJS-$(CONFIG_SPI_FLASH_SPANSION)	+= spansion.o
-COBJS-$(CONFIG_SPI_FLASH_SST)	+= sst.o
-COBJS-$(CONFIG_SPI_FLASH_STMICRO)	+= stmicro.o
-COBJS-$(CONFIG_SPI_FLASH_WINBOND)	+= winbond.o
-COBJS-$(CONFIG_SPI_FRAM_RAMTRON)	+= ramtron.o
+ifdef CONFIG_CMD_SF
+COBJS-y        += sf.o
+endif
+COBJS-$(CONFIG_SPI_FLASH) += sf_probe.o sf_ops.o
+COBJS-$(CONFIG_SPI_FRAM_RAMTRON) += ramtron.o
 COBJS-$(CONFIG_SPI_M95XXX) += eeprom_m95xxx.o
 
 COBJS	:= $(COBJS-y)
diff --git a/drivers/mtd/spi/atmel.c b/drivers/mtd/spi/atmel.c
deleted file mode 100644
index f34df43..0000000
--- a/drivers/mtd/spi/atmel.c
+++ /dev/null
@@ -1,544 +0,0 @@
-/*
- * Atmel SPI DataFlash support
- *
- * Copyright (C) 2008 Atmel Corporation
- * Licensed under the GPL-2 or later.
- */
-
-#include <common.h>
-#include <malloc.h>
-#include <spi_flash.h>
-
-#include "spi_flash_internal.h"
-
-/* AT45-specific commands */
-#define CMD_AT45_READ_STATUS		0xd7
-#define CMD_AT45_ERASE_PAGE		0x81
-#define CMD_AT45_LOAD_PROG_BUF1		0x82
-#define CMD_AT45_LOAD_BUF1		0x84
-#define CMD_AT45_LOAD_PROG_BUF2		0x85
-#define CMD_AT45_LOAD_BUF2		0x87
-#define CMD_AT45_PROG_BUF1		0x88
-#define CMD_AT45_PROG_BUF2		0x89
-
-/* AT45 status register bits */
-#define AT45_STATUS_P2_PAGE_SIZE	(1 << 0)
-#define AT45_STATUS_READY		(1 << 7)
-
-/* DataFlash family IDs, as obtained from the second idcode byte */
-#define DF_FAMILY_AT26F			0
-#define DF_FAMILY_AT45			1
-#define DF_FAMILY_AT26DF		2	/* AT25DF and AT26DF */
-
-struct atmel_spi_flash_params {
-	u8		idcode1;
-	/* Log2 of page size in power-of-two mode */
-	u8		l2_page_size;
-	u8		pages_per_block;
-	u8		blocks_per_sector;
-	u8		nr_sectors;
-	const char	*name;
-};
-
-/* spi_flash needs to be first so upper layers can free() it */
-struct atmel_spi_flash {
-	struct spi_flash flash;
-	const struct atmel_spi_flash_params *params;
-};
-
-static inline struct atmel_spi_flash *
-to_atmel_spi_flash(struct spi_flash *flash)
-{
-	return container_of(flash, struct atmel_spi_flash, flash);
-}
-
-static const struct atmel_spi_flash_params atmel_spi_flash_table[] = {
-	{
-		.idcode1		= 0x22,
-		.l2_page_size		= 8,
-		.pages_per_block	= 8,
-		.blocks_per_sector	= 16,
-		.nr_sectors		= 4,
-		.name			= "AT45DB011D",
-	},
-	{
-		.idcode1		= 0x23,
-		.l2_page_size		= 8,
-		.pages_per_block	= 8,
-		.blocks_per_sector	= 16,
-		.nr_sectors		= 8,
-		.name			= "AT45DB021D",
-	},
-	{
-		.idcode1		= 0x24,
-		.l2_page_size		= 8,
-		.pages_per_block	= 8,
-		.blocks_per_sector	= 32,
-		.nr_sectors		= 8,
-		.name			= "AT45DB041D",
-	},
-	{
-		.idcode1		= 0x25,
-		.l2_page_size		= 8,
-		.pages_per_block	= 8,
-		.blocks_per_sector	= 32,
-		.nr_sectors		= 16,
-		.name			= "AT45DB081D",
-	},
-	{
-		.idcode1		= 0x26,
-		.l2_page_size		= 9,
-		.pages_per_block	= 8,
-		.blocks_per_sector	= 32,
-		.nr_sectors		= 16,
-		.name			= "AT45DB161D",
-	},
-	{
-		.idcode1		= 0x27,
-		.l2_page_size		= 9,
-		.pages_per_block	= 8,
-		.blocks_per_sector	= 64,
-		.nr_sectors		= 64,
-		.name			= "AT45DB321D",
-	},
-	{
-		.idcode1		= 0x28,
-		.l2_page_size		= 10,
-		.pages_per_block	= 8,
-		.blocks_per_sector	= 32,
-		.nr_sectors		= 32,
-		.name			= "AT45DB642D",
-	},
-	{
-		.idcode1		= 0x47,
-		.l2_page_size		= 8,
-		.pages_per_block	= 16,
-		.blocks_per_sector	= 16,
-		.nr_sectors		= 64,
-		.name			= "AT25DF321",
-	},
-};
-
-static int at45_wait_ready(struct spi_flash *flash, unsigned long timeout)
-{
-	struct spi_slave *spi = flash->spi;
-	unsigned long timebase;
-	int ret;
-	u8 cmd = CMD_AT45_READ_STATUS;
-	u8 status;
-
-	timebase = get_timer(0);
-
-	ret = spi_xfer(spi, 8, &cmd, NULL, SPI_XFER_BEGIN);
-	if (ret)
-		return -1;
-
-	do {
-		ret = spi_xfer(spi, 8, NULL, &status, 0);
-		if (ret)
-			return -1;
-
-		if (status & AT45_STATUS_READY)
-			break;
-	} while (get_timer(timebase) < timeout);
-
-	/* Deactivate CS */
-	spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END);
-
-	if (status & AT45_STATUS_READY)
-		return 0;
-
-	/* Timed out */
-	return -1;
-}
-
-/*
- * Assemble the address part of a command for AT45 devices in
- * non-power-of-two page size mode.
- */
-static void at45_build_address(struct atmel_spi_flash *asf, u8 *cmd, u32 offset)
-{
-	unsigned long page_addr;
-	unsigned long byte_addr;
-	unsigned long page_size;
-	unsigned int page_shift;
-
-	/*
-	 * The "extra" space per page is the power-of-two page size
-	 * divided by 32.
-	 */
-	page_shift = asf->params->l2_page_size;
-	page_size = (1 << page_shift) + (1 << (page_shift - 5));
-	page_shift++;
-	page_addr = offset / page_size;
-	byte_addr = offset % page_size;
-
-	cmd[0] = page_addr >> (16 - page_shift);
-	cmd[1] = page_addr << (page_shift - 8) | (byte_addr >> 8);
-	cmd[2] = byte_addr;
-}
-
-static int dataflash_read_fast_at45(struct spi_flash *flash,
-		u32 offset, size_t len, void *buf)
-{
-	struct atmel_spi_flash *asf = to_atmel_spi_flash(flash);
-	u8 cmd[5];
-
-	cmd[0] = CMD_READ_ARRAY_FAST;
-	at45_build_address(asf, cmd + 1, offset);
-	cmd[4] = 0x00;
-
-	return spi_flash_read_common(flash, cmd, sizeof(cmd), buf, len);
-}
-
-/*
- * TODO: the two write funcs (_p2/_at45) should get unified ...
- */
-static int dataflash_write_p2(struct spi_flash *flash,
-		u32 offset, size_t len, const void *buf)
-{
-	struct atmel_spi_flash *asf = to_atmel_spi_flash(flash);
-	unsigned long page_size;
-	u32 addr = offset;
-	size_t chunk_len;
-	size_t actual;
-	int ret;
-	u8 cmd[4];
-
-	/*
-	 * TODO: This function currently uses only page buffer #1.  We can
-	 * speed this up by using both buffers and loading one buffer while
-	 * the other is being programmed into main memory.
-	 */
-
-	page_size = (1 << asf->params->l2_page_size);
-
-	ret = spi_claim_bus(flash->spi);
-	if (ret) {
-		debug("SF: Unable to claim SPI bus\n");
-		return ret;
-	}
-
-	for (actual = 0; actual < len; actual += chunk_len) {
-		chunk_len = min(len - actual, page_size - (addr % page_size));
-
-		/* Use the same address bits for both commands */
-		cmd[0] = CMD_AT45_LOAD_BUF1;
-		cmd[1] = addr >> 16;
-		cmd[2] = addr >> 8;
-		cmd[3] = addr;
-
-		ret = spi_flash_cmd_write(flash->spi, cmd, 4,
-				buf + actual, chunk_len);
-		if (ret < 0) {
-			debug("SF: Loading AT45 buffer failed\n");
-			goto out;
-		}
-
-		cmd[0] = CMD_AT45_PROG_BUF1;
-		ret = spi_flash_cmd_write(flash->spi, cmd, 4, NULL, 0);
-		if (ret < 0) {
-			debug("SF: AT45 page programming failed\n");
-			goto out;
-		}
-
-		ret = at45_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
-		if (ret < 0) {
-			debug("SF: AT45 page programming timed out\n");
-			goto out;
-		}
-
-		addr += chunk_len;
-	}
-
-	debug("SF: AT45: Successfully programmed %zu bytes @ 0x%x\n",
-	      len, offset);
-	ret = 0;
-
-out:
-	spi_release_bus(flash->spi);
-	return ret;
-}
-
-static int dataflash_write_at45(struct spi_flash *flash,
-		u32 offset, size_t len, const void *buf)
-{
-	struct atmel_spi_flash *asf = to_atmel_spi_flash(flash);
-	unsigned long page_addr;
-	unsigned long byte_addr;
-	unsigned long page_size;
-	unsigned int page_shift;
-	size_t chunk_len;
-	size_t actual;
-	int ret;
-	u8 cmd[4];
-
-	/*
-	 * TODO: This function currently uses only page buffer #1.  We can
-	 * speed this up by using both buffers and loading one buffer while
-	 * the other is being programmed into main memory.
-	 */
-
-	page_shift = asf->params->l2_page_size;
-	page_size = (1 << page_shift) + (1 << (page_shift - 5));
-	page_shift++;
-	page_addr = offset / page_size;
-	byte_addr = offset % page_size;
-
-	ret = spi_claim_bus(flash->spi);
-	if (ret) {
-		debug("SF: Unable to claim SPI bus\n");
-		return ret;
-	}
-
-	for (actual = 0; actual < len; actual += chunk_len) {
-		chunk_len = min(len - actual, page_size - byte_addr);
-
-		/* Use the same address bits for both commands */
-		cmd[0] = CMD_AT45_LOAD_BUF1;
-		cmd[1] = page_addr >> (16 - page_shift);
-		cmd[2] = page_addr << (page_shift - 8) | (byte_addr >> 8);
-		cmd[3] = byte_addr;
-
-		ret = spi_flash_cmd_write(flash->spi, cmd, 4,
-				buf + actual, chunk_len);
-		if (ret < 0) {
-			debug("SF: Loading AT45 buffer failed\n");
-			goto out;
-		}
-
-		cmd[0] = CMD_AT45_PROG_BUF1;
-		ret = spi_flash_cmd_write(flash->spi, cmd, 4, NULL, 0);
-		if (ret < 0) {
-			debug("SF: AT45 page programming failed\n");
-			goto out;
-		}
-
-		ret = at45_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
-		if (ret < 0) {
-			debug("SF: AT45 page programming timed out\n");
-			goto out;
-		}
-
-		page_addr++;
-		byte_addr = 0;
-	}
-
-	debug("SF: AT45: Successfully programmed %zu bytes @ 0x%x\n",
-	      len, offset);
-	ret = 0;
-
-out:
-	spi_release_bus(flash->spi);
-	return ret;
-}
-
-/*
- * TODO: the two erase funcs (_p2/_at45) should get unified ...
- */
-static int dataflash_erase_p2(struct spi_flash *flash, u32 offset, size_t len)
-{
-	struct atmel_spi_flash *asf = to_atmel_spi_flash(flash);
-	unsigned long page_size;
-
-	size_t actual;
-	int ret;
-	u8 cmd[4];
-
-	/*
-	 * TODO: This function currently uses page erase only. We can
-	 * probably speed things up by using block and/or sector erase
-	 * when possible.
-	 */
-
-	page_size = (1 << asf->params->l2_page_size);
-
-	if (offset % page_size || len % page_size) {
-		debug("SF: Erase offset/length not multiple of page size\n");
-		return -1;
-	}
-
-	cmd[0] = CMD_AT45_ERASE_PAGE;
-	cmd[3] = 0x00;
-
-	ret = spi_claim_bus(flash->spi);
-	if (ret) {
-		debug("SF: Unable to claim SPI bus\n");
-		return ret;
-	}
-
-	for (actual = 0; actual < len; actual += page_size) {
-		cmd[1] = offset >> 16;
-		cmd[2] = offset >> 8;
-
-		ret = spi_flash_cmd_write(flash->spi, cmd, 4, NULL, 0);
-		if (ret < 0) {
-			debug("SF: AT45 page erase failed\n");
-			goto out;
-		}
-
-		ret = at45_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT);
-		if (ret < 0) {
-			debug("SF: AT45 page erase timed out\n");
-			goto out;
-		}
-
-		offset += page_size;
-	}
-
-	debug("SF: AT45: Successfully erased %zu bytes @ 0x%x\n",
-	      len, offset);
-	ret = 0;
-
-out:
-	spi_release_bus(flash->spi);
-	return ret;
-}
-
-static int dataflash_erase_at45(struct spi_flash *flash, u32 offset, size_t len)
-{
-	struct atmel_spi_flash *asf = to_atmel_spi_flash(flash);
-	unsigned long page_addr;
-	unsigned long page_size;
-	unsigned int page_shift;
-	size_t actual;
-	int ret;
-	u8 cmd[4];
-
-	/*
-	 * TODO: This function currently uses page erase only. We can
-	 * probably speed things up by using block and/or sector erase
-	 * when possible.
-	 */
-
-	page_shift = asf->params->l2_page_size;
-	page_size = (1 << page_shift) + (1 << (page_shift - 5));
-	page_shift++;
-	page_addr = offset / page_size;
-
-	if (offset % page_size || len % page_size) {
-		debug("SF: Erase offset/length not multiple of page size\n");
-		return -1;
-	}
-
-	cmd[0] = CMD_AT45_ERASE_PAGE;
-	cmd[3] = 0x00;
-
-	ret = spi_claim_bus(flash->spi);
-	if (ret) {
-		debug("SF: Unable to claim SPI bus\n");
-		return ret;
-	}
-
-	for (actual = 0; actual < len; actual += page_size) {
-		cmd[1] = page_addr >> (16 - page_shift);
-		cmd[2] = page_addr << (page_shift - 8);
-
-		ret = spi_flash_cmd_write(flash->spi, cmd, 4, NULL, 0);
-		if (ret < 0) {
-			debug("SF: AT45 page erase failed\n");
-			goto out;
-		}
-
-		ret = at45_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT);
-		if (ret < 0) {
-			debug("SF: AT45 page erase timed out\n");
-			goto out;
-		}
-
-		page_addr++;
-	}
-
-	debug("SF: AT45: Successfully erased %zu bytes @ 0x%x\n",
-	      len, offset);
-	ret = 0;
-
-out:
-	spi_release_bus(flash->spi);
-	return ret;
-}
-
-struct spi_flash *spi_flash_probe_atmel(struct spi_slave *spi, u8 *idcode)
-{
-	const struct atmel_spi_flash_params *params;
-	unsigned page_size;
-	unsigned int family;
-	struct atmel_spi_flash *asf;
-	unsigned int i;
-	int ret;
-	u8 status;
-
-	for (i = 0; i < ARRAY_SIZE(atmel_spi_flash_table); i++) {
-		params = &atmel_spi_flash_table[i];
-		if (params->idcode1 == idcode[1])
-			break;
-	}
-
-	if (i == ARRAY_SIZE(atmel_spi_flash_table)) {
-		debug("SF: Unsupported DataFlash ID %02x\n",
-		      idcode[1]);
-		return NULL;
-	}
-
-	asf = spi_flash_alloc(struct atmel_spi_flash, spi, params->name);
-	if (!asf) {
-		debug("SF: Failed to allocate memory\n");
-		return NULL;
-	}
-
-	asf->params = params;
-
-	/* Assuming power-of-two page size initially. */
-	page_size = 1 << params->l2_page_size;
-
-	family = idcode[1] >> 5;
-
-	switch (family) {
-	case DF_FAMILY_AT45:
-		/*
-		 * AT45 chips have configurable page size. The status
-		 * register indicates which configuration is active.
-		 */
-		ret = spi_flash_cmd(spi, CMD_AT45_READ_STATUS, &status, 1);
-		if (ret)
-			goto err;
-
-		debug("SF: AT45 status register: %02x\n", status);
-
-		if (!(status & AT45_STATUS_P2_PAGE_SIZE)) {
-			asf->flash.read = dataflash_read_fast_at45;
-			asf->flash.write = dataflash_write_at45;
-			asf->flash.erase = dataflash_erase_at45;
-			page_size += 1 << (params->l2_page_size - 5);
-		} else {
-			asf->flash.write = dataflash_write_p2;
-			asf->flash.erase = dataflash_erase_p2;
-		}
-
-		asf->flash.page_size = page_size;
-		asf->flash.sector_size = page_size;
-		break;
-
-	case DF_FAMILY_AT26F:
-	case DF_FAMILY_AT26DF:
-		asf->flash.page_size = page_size;
-		asf->flash.sector_size = 4096;
-		/* clear SPRL# bit for locked flash */
-		spi_flash_cmd_write_status(&asf->flash, 0);
-		break;
-
-	default:
-		debug("SF: Unsupported DataFlash family %u\n", family);
-		goto err;
-	}
-
-	asf->flash.size = page_size * params->pages_per_block
-				* params->blocks_per_sector
-				* params->nr_sectors;
-
-	return &asf->flash;
-
-err:
-	free(asf);
-	return NULL;
-}
diff --git a/drivers/mtd/spi/eon.c b/drivers/mtd/spi/eon.c
deleted file mode 100644
index 25cfc12..0000000
--- a/drivers/mtd/spi/eon.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * (C) Copyright 2010, ucRobotics Inc.
- * Author: Chong Huang <chuang@ucrobotics.com>
- * Licensed under the GPL-2 or later.
- */
-
-#include <common.h>
-#include <malloc.h>
-#include <spi_flash.h>
-
-#include "spi_flash_internal.h"
-
-struct eon_spi_flash_params {
-	u8 idcode1;
-	u16 nr_sectors;
-	const char *name;
-};
-
-static const struct eon_spi_flash_params eon_spi_flash_table[] = {
-	{
-		.idcode1 = 0x16,
-		.nr_sectors = 1024,
-		.name = "EN25Q32B",
-	},
-	{
-		.idcode1 = 0x18,
-		.nr_sectors = 4096,
-		.name = "EN25Q128",
-	},
-};
-
-struct spi_flash *spi_flash_probe_eon(struct spi_slave *spi, u8 *idcode)
-{
-	const struct eon_spi_flash_params *params;
-	struct spi_flash *flash;
-	unsigned int i;
-
-	for (i = 0; i < ARRAY_SIZE(eon_spi_flash_table); ++i) {
-		params = &eon_spi_flash_table[i];
-		if (params->idcode1 == idcode[2])
-			break;
-	}
-
-	if (i == ARRAY_SIZE(eon_spi_flash_table)) {
-		debug("SF: Unsupported EON ID %02x\n", idcode[1]);
-		return NULL;
-	}
-
-	flash = spi_flash_alloc_base(spi, params->name);
-	if (!flash) {
-		debug("SF: Failed to allocate memory\n");
-		return NULL;
-	}
-
-	flash->page_size = 256;
-	flash->sector_size = 256 * 16 * 16;
-	flash->size = 256 * 16 * params->nr_sectors;
-
-	return flash;
-}
diff --git a/drivers/mtd/spi/gigadevice.c b/drivers/mtd/spi/gigadevice.c
deleted file mode 100644
index b42581a..0000000
--- a/drivers/mtd/spi/gigadevice.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Gigadevice SPI flash driver
- * Copyright 2013, Samsung Electronics Co., Ltd.
- * Author: Banajit Goswami <banajit.g@samsung.com>
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <common.h>
-#include <malloc.h>
-#include <spi_flash.h>
-
-#include "spi_flash_internal.h"
-
-struct gigadevice_spi_flash_params {
-	uint16_t	id;
-	uint16_t	nr_blocks;
-	const char	*name;
-};
-
-static const struct gigadevice_spi_flash_params gigadevice_spi_flash_table[] = {
-	{
-		.id			= 0x6016,
-		.nr_blocks		= 64,
-		.name			= "GD25LQ",
-	},
-	{
-		.id			= 0x4017,
-		.nr_blocks		= 128,
-		.name			= "GD25Q64B",
-	},
-};
-
-struct spi_flash *spi_flash_probe_gigadevice(struct spi_slave *spi, u8 *idcode)
-{
-	const struct gigadevice_spi_flash_params *params;
-	struct spi_flash *flash;
-	unsigned int i;
-
-	for (i = 0; i < ARRAY_SIZE(gigadevice_spi_flash_table); i++) {
-		params = &gigadevice_spi_flash_table[i];
-		if (params->id == ((idcode[1] << 8) | idcode[2]))
-			break;
-	}
-
-	if (i == ARRAY_SIZE(gigadevice_spi_flash_table)) {
-		debug("SF: Unsupported Gigadevice ID %02x%02x\n",
-		      idcode[1], idcode[2]);
-		return NULL;
-	}
-
-	flash = spi_flash_alloc_base(spi, params->name);
-	if (!flash) {
-		debug("SF: Failed to allocate memory\n");
-		return NULL;
-	}
-	/* page_size */
-	flash->page_size = 256;
-	/* sector_size = page_size * pages_per_sector */
-	flash->sector_size = flash->page_size * 16;
-	/* size = sector_size * sector_per_block * number of blocks */
-	flash->size = flash->sector_size * 16 * params->nr_blocks;
-
-	return flash;
-}
diff --git a/drivers/mtd/spi/macronix.c b/drivers/mtd/spi/macronix.c
deleted file mode 100644
index 70435eb..0000000
--- a/drivers/mtd/spi/macronix.c
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright 2009(C) Marvell International Ltd. and its affiliates
- * Prafulla Wadaskar <prafulla@marvell.com>
- *
- * Based on drivers/mtd/spi/stmicro.c
- *
- * Copyright 2008, Network Appliance Inc.
- * Jason McMullan <mcmullan@netapp.com>
- *
- * Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
- * TsiChung Liew (Tsi-Chung.Liew@freescale.com)
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <common.h>
-#include <malloc.h>
-#include <spi_flash.h>
-
-#include "spi_flash_internal.h"
-
-struct macronix_spi_flash_params {
-	u16 idcode;
-	u16 nr_blocks;
-	const char *name;
-};
-
-static const struct macronix_spi_flash_params macronix_spi_flash_table[] = {
-	{
-		.idcode = 0x2013,
-		.nr_blocks = 8,
-		.name = "MX25L4005",
-	},
-	{
-		.idcode = 0x2014,
-		.nr_blocks = 16,
-		.name = "MX25L8005",
-	},
-	{
-		.idcode = 0x2015,
-		.nr_blocks = 32,
-		.name = "MX25L1605D",
-	},
-	{
-		.idcode = 0x2016,
-		.nr_blocks = 64,
-		.name = "MX25L3205D",
-	},
-	{
-		.idcode = 0x2017,
-		.nr_blocks = 128,
-		.name = "MX25L6405D",
-	},
-	{
-		.idcode = 0x2018,
-		.nr_blocks = 256,
-		.name = "MX25L12805D",
-	},
-	{
-		.idcode = 0x2618,
-		.nr_blocks = 256,
-		.name = "MX25L12855E",
-	},
-};
-
-struct spi_flash *spi_flash_probe_macronix(struct spi_slave *spi, u8 *idcode)
-{
-	const struct macronix_spi_flash_params *params;
-	struct spi_flash *flash;
-	unsigned int i;
-	u16 id = idcode[2] | idcode[1] << 8;
-
-	for (i = 0; i < ARRAY_SIZE(macronix_spi_flash_table); i++) {
-		params = &macronix_spi_flash_table[i];
-		if (params->idcode == id)
-			break;
-	}
-
-	if (i == ARRAY_SIZE(macronix_spi_flash_table)) {
-		debug("SF: Unsupported Macronix ID %04x\n", id);
-		return NULL;
-	}
-
-	flash = spi_flash_alloc_base(spi, params->name);
-	if (!flash) {
-		debug("SF: Failed to allocate memory\n");
-		return NULL;
-	}
-
-	flash->page_size = 256;
-	flash->sector_size = 256 * 16 * 16;
-	flash->size = flash->sector_size * params->nr_blocks;
-
-	/* Clear BP# bits for read-only flash */
-	spi_flash_cmd_write_status(flash, 0);
-
-	return flash;
-}
diff --git a/drivers/mtd/spi/ramtron.c b/drivers/mtd/spi/ramtron.c
index 38f9d69..d50da37 100644
--- a/drivers/mtd/spi/ramtron.c
+++ b/drivers/mtd/spi/ramtron.c
@@ -36,7 +36,7 @@
 #include <common.h>
 #include <malloc.h>
 #include <spi_flash.h>
-#include "spi_flash_internal.h"
+#include "sf_internal.h"
 
 /*
  * Properties of supported FRAMs
@@ -214,7 +214,8 @@
  * nore: we are called here with idcode pointing to the first non-0x7f byte
  * already!
  */
-struct spi_flash *spi_fram_probe_ramtron(struct spi_slave *spi, u8 *idcode)
+static struct spi_flash *spi_fram_probe_ramtron(struct spi_slave *spi,
+		u8 *idcode)
 {
 	const struct ramtron_spi_fram_params *params;
 	struct ramtron_spi_fram *sn;
@@ -270,7 +271,7 @@
 	return NULL;
 
 found:
-	sn = spi_flash_alloc(struct ramtron_spi_fram, spi, params->name);
+	sn = malloc(sizeof(*sn));
 	if (!sn) {
 		debug("SF: Failed to allocate memory\n");
 		return NULL;
@@ -285,3 +286,118 @@
 
 	return &sn->flash;
 }
+
+/*
+ * The following table holds all device probe functions
+ * (All flashes are removed and implemented a common probe at
+ *  spi_flash_probe.c)
+ *
+ * shift:  number of continuation bytes before the ID
+ * idcode: the expected IDCODE or 0xff for non JEDEC devices
+ * probe:  the function to call
+ *
+ * Non JEDEC devices should be ordered in the table such that
+ * the probe functions with best detection algorithms come first.
+ *
+ * Several matching entries are permitted, they will be tried
+ * in sequence until a probe function returns non NULL.
+ *
+ * IDCODE_CONT_LEN may be redefined if a device needs to declare a
+ * larger "shift" value.  IDCODE_PART_LEN generally shouldn't be
+ * changed.  This is the max number of bytes probe functions may
+ * examine when looking up part-specific identification info.
+ *
+ * Probe functions will be given the idcode buffer starting at their
+ * manu id byte (the "idcode" in the table below).  In other words,
+ * all of the continuation bytes will be skipped (the "shift" below).
+ */
+#define IDCODE_CONT_LEN 0
+#define IDCODE_PART_LEN 5
+static const struct {
+	const u8 shift;
+	const u8 idcode;
+	struct spi_flash *(*probe) (struct spi_slave *spi, u8 *idcode);
+} flashes[] = {
+	/* Keep it sorted by define name */
+#ifdef CONFIG_SPI_FRAM_RAMTRON
+	{ 6, 0xc2, spi_fram_probe_ramtron, },
+# undef IDCODE_CONT_LEN
+# define IDCODE_CONT_LEN 6
+#endif
+#ifdef CONFIG_SPI_FRAM_RAMTRON_NON_JEDEC
+	{ 0, 0xff, spi_fram_probe_ramtron, },
+#endif
+};
+#define IDCODE_LEN (IDCODE_CONT_LEN + IDCODE_PART_LEN)
+
+struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
+		unsigned int max_hz, unsigned int spi_mode)
+{
+	struct spi_slave *spi;
+	struct spi_flash *flash = NULL;
+	int ret, i, shift;
+	u8 idcode[IDCODE_LEN], *idp;
+
+	spi = spi_setup_slave(bus, cs, max_hz, spi_mode);
+	if (!spi) {
+		printf("SF: Failed to set up slave\n");
+		return NULL;
+	}
+
+	ret = spi_claim_bus(spi);
+	if (ret) {
+		debug("SF: Failed to claim SPI bus: %d\n", ret);
+		goto err_claim_bus;
+	}
+
+	/* Read the ID codes */
+	ret = spi_flash_cmd(spi, CMD_READ_ID, idcode, sizeof(idcode));
+	if (ret)
+		goto err_read_id;
+
+#ifdef DEBUG
+	printf("SF: Got idcodes\n");
+	print_buffer(0, idcode, 1, sizeof(idcode), 0);
+#endif
+
+	/* count the number of continuation bytes */
+	for (shift = 0, idp = idcode;
+	     shift < IDCODE_CONT_LEN && *idp == 0x7f;
+	     ++shift, ++idp)
+		continue;
+
+	/* search the table for matches in shift and id */
+	for (i = 0; i < ARRAY_SIZE(flashes); ++i)
+		if (flashes[i].shift == shift && flashes[i].idcode == *idp) {
+			/* we have a match, call probe */
+			flash = flashes[i].probe(spi, idp);
+			if (flash)
+				break;
+		}
+
+	if (!flash) {
+		printf("SF: Unsupported manufacturer %02x\n", *idp);
+		goto err_manufacturer_probe;
+	}
+
+	printf("SF: Detected %s with total size ", flash->name);
+	print_size(flash->size, "");
+	puts("\n");
+
+	spi_release_bus(spi);
+
+	return flash;
+
+err_manufacturer_probe:
+err_read_id:
+	spi_release_bus(spi);
+err_claim_bus:
+	spi_free_slave(spi);
+	return NULL;
+}
+
+void spi_flash_free(struct spi_flash *flash)
+{
+	spi_free_slave(flash->spi);
+	free(flash);
+}
diff --git a/drivers/mtd/spi/sf.c b/drivers/mtd/spi/sf.c
new file mode 100644
index 0000000..ddbdda0
--- /dev/null
+++ b/drivers/mtd/spi/sf.c
@@ -0,0 +1,54 @@
+/*
+ * SPI flash interface
+ *
+ * Copyright (C) 2008 Atmel Corporation
+ * Copyright (C) 2010 Reinhard Meyer, EMK Elektronik
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <common.h>
+#include <spi.h>
+
+static int spi_flash_read_write(struct spi_slave *spi,
+				const u8 *cmd, size_t cmd_len,
+				const u8 *data_out, u8 *data_in,
+				size_t data_len)
+{
+	unsigned long flags = SPI_XFER_BEGIN;
+	int ret;
+
+	if (data_len == 0)
+		flags |= SPI_XFER_END;
+
+	ret = spi_xfer(spi, cmd_len * 8, cmd, NULL, flags);
+	if (ret) {
+		debug("SF: Failed to send command (%zu bytes): %d\n",
+		      cmd_len, ret);
+	} else if (data_len != 0) {
+		ret = spi_xfer(spi, data_len * 8, data_out, data_in,
+					SPI_XFER_END);
+		if (ret)
+			debug("SF: Failed to transfer %zu bytes of data: %d\n",
+			      data_len, ret);
+	}
+
+	return ret;
+}
+
+int spi_flash_cmd_read(struct spi_slave *spi, const u8 *cmd,
+		size_t cmd_len, void *data, size_t data_len)
+{
+	return spi_flash_read_write(spi, cmd, cmd_len, NULL, data, data_len);
+}
+
+int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len)
+{
+	return spi_flash_cmd_read(spi, &cmd, 1, response, len);
+}
+
+int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len,
+		const void *data, size_t data_len)
+{
+	return spi_flash_read_write(spi, cmd, cmd_len, data, NULL, data_len);
+}
diff --git a/drivers/mtd/spi/spi_flash_internal.h b/drivers/mtd/spi/sf_internal.h
similarity index 62%
rename from drivers/mtd/spi/spi_flash_internal.h
rename to drivers/mtd/spi/sf_internal.h
index af1afa9..12d02f9 100644
--- a/drivers/mtd/spi/spi_flash_internal.h
+++ b/drivers/mtd/spi/sf_internal.h
@@ -2,42 +2,43 @@
  * SPI flash internal definitions
  *
  * Copyright (C) 2008 Atmel Corporation
+ * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc.
+ *
+ * Licensed under the GPL-2 or later.
  */
 
-/* Common parameters -- kind of high, but they should only occur when there
- * is a problem (and well your system already is broken), so err on the side
- * of caution in case we're dealing with slower SPI buses and/or processors.
- */
-#define SPI_FLASH_PROG_TIMEOUT		(2 * CONFIG_SYS_HZ)
-#define SPI_FLASH_PAGE_ERASE_TIMEOUT	(5 * CONFIG_SYS_HZ)
-#define SPI_FLASH_SECTOR_ERASE_TIMEOUT	(10 * CONFIG_SYS_HZ)
+#ifndef _SPI_FLASH_INTERNAL_H_
+#define _SPI_FLASH_INTERNAL_H_
 
-/* Common commands */
-#define CMD_READ_ID			0x9f
+#define SPI_FLASH_16MB_BOUN		0x1000000
 
-#define CMD_READ_ARRAY_SLOW		0x03
-#define CMD_READ_ARRAY_FAST		0x0b
+/* SECT flags */
+#define SECT_4K				(1 << 1)
+#define SECT_32K			(1 << 2)
+#define E_FSR				(1 << 3)
 
+/* Erase commands */
+#define CMD_ERASE_4K			0x20
+#define CMD_ERASE_32K			0x52
+#define CMD_ERASE_CHIP			0xc7
+#define CMD_ERASE_64K			0xd8
+
+/* Write commands */
 #define CMD_WRITE_STATUS		0x01
 #define CMD_PAGE_PROGRAM		0x02
 #define CMD_WRITE_DISABLE		0x04
 #define CMD_READ_STATUS			0x05
-#define CMD_FLAG_STATUS			0x70
 #define CMD_WRITE_ENABLE		0x06
-#define CMD_ERASE_4K			0x20
-#define CMD_ERASE_32K			0x52
-#define CMD_ERASE_64K			0xd8
-#define CMD_ERASE_CHIP			0xc7
-
-#define SPI_FLASH_16MB_BOUN		0x1000000
+#define CMD_READ_CONFIG			0x35
+#define CMD_FLAG_STATUS			0x70
 
-/* Manufacture ID's */
-#define SPI_FLASH_SPANSION_IDCODE0	0x01
-#define SPI_FLASH_STMICRO_IDCODE0	0x20
-#define SPI_FLASH_WINBOND_IDCODE0	0xef
+/* Read commands */
+#define CMD_READ_ARRAY_SLOW		0x03
+#define CMD_READ_ARRAY_FAST		0x0b
+#define CMD_READ_ID			0x9f
 
-#ifdef CONFIG_SPI_FLASH_BAR
 /* Bank addr access commands */
+#ifdef CONFIG_SPI_FLASH_BAR
 # define CMD_BANKADDR_BRWR		0x17
 # define CMD_BANKADDR_BRRD		0x16
 # define CMD_EXTNADDR_WREAR		0xC5
@@ -48,6 +49,21 @@
 #define STATUS_WIP			0x01
 #define STATUS_PEC			0x80
 
+/* Flash timeout values */
+#define SPI_FLASH_PROG_TIMEOUT		(2 * CONFIG_SYS_HZ)
+#define SPI_FLASH_PAGE_ERASE_TIMEOUT	(5 * CONFIG_SYS_HZ)
+#define SPI_FLASH_SECTOR_ERASE_TIMEOUT	(10 * CONFIG_SYS_HZ)
+
+/* SST specific */
+#ifdef CONFIG_SPI_FLASH_SST
+# define SST_WP			0x01	/* Supports AAI word program */
+# define CMD_SST_BP		0x02    /* Byte Program */
+# define CMD_SST_AAI_WP		0xAD	/* Auto Address Incr Word Program */
+
+int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len,
+		const void *buf);
+#endif
+
 /* Send a single-byte command to the device and read the response */
 int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len);
 
@@ -58,9 +74,6 @@
 int spi_flash_cmd_read(struct spi_slave *spi, const u8 *cmd,
 		size_t cmd_len, void *data, size_t data_len);
 
-int spi_flash_cmd_read_fast(struct spi_flash *flash, u32 offset,
-		size_t len, void *data);
-
 /*
  * Send a multi-byte command to the device followed by (optional)
  * data. Used for programming the flash array, etc.
@@ -68,46 +81,34 @@
 int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len,
 		const void *data, size_t data_len);
 
-/*
- * Write the requested data out breaking it up into multiple write
- * commands as needed per the write size.
- */
-int spi_flash_cmd_write_multi(struct spi_flash *flash, u32 offset,
-		size_t len, const void *buf);
 
-/*
- * Enable writing on the SPI flash.
- */
+/* Flash erase(sectors) operation, support all possible erase commands */
+int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len);
+
+/* Program the status register */
+int spi_flash_cmd_write_status(struct spi_flash *flash, u8 sr);
+
+/* Set quad enbale bit */
+int spi_flash_set_qeb(struct spi_flash *flash);
+
+/* Enable writing on the SPI flash */
 static inline int spi_flash_cmd_write_enable(struct spi_flash *flash)
 {
 	return spi_flash_cmd(flash->spi, CMD_WRITE_ENABLE, NULL, 0);
 }
 
-/*
- * Disable writing on the SPI flash.
- */
+/* Disable writing on the SPI flash */
 static inline int spi_flash_cmd_write_disable(struct spi_flash *flash)
 {
 	return spi_flash_cmd(flash->spi, CMD_WRITE_DISABLE, NULL, 0);
 }
 
-/* Program the status register. */
-int spi_flash_cmd_write_status(struct spi_flash *flash, u8 sr);
-
-#ifdef CONFIG_SPI_FLASH_BAR
-/* Program the bank address register */
-int spi_flash_cmd_bankaddr_write(struct spi_flash *flash, u8 bank_sel);
-
-/* Configure the BAR - discover the bank cmds */
-int spi_flash_bank_config(struct spi_flash *flash, u8 idcode0);
-#endif
-
 /*
- * Same as spi_flash_cmd_read() except it also claims/releases the SPI
- * bus. Used as common part of the ->read() operation.
+ * Send the read status command to the device and wait for the wip
+ * (write-in-progress) bit to clear itself.
  */
-int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd,
-		size_t cmd_len, void *data, size_t data_len);
+int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout);
+
 /*
  * Used for spi_flash write operation
  * - SPI claim
@@ -120,21 +121,22 @@
 		size_t cmd_len, const void *buf, size_t buf_len);
 
 /*
- * Send the read status command to the device and wait for the wip
- * (write-in-progress) bit to clear itself.
+ * Flash write operation, support all possible write commands.
+ * Write the requested data out breaking it up into multiple write
+ * commands as needed per the write size.
  */
-int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout);
+int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset,
+		size_t len, const void *buf);
 
-/* Erase sectors. */
-int spi_flash_cmd_erase(struct spi_flash *flash, u32 offset, size_t len);
+/*
+ * Same as spi_flash_cmd_read() except it also claims/releases the SPI
+ * bus. Used as common part of the ->read() operation.
+ */
+int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd,
+		size_t cmd_len, void *data, size_t data_len);
+
+/* Flash read operation, support all possible read commands */
+int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset,
+		size_t len, void *data);
 
-/* Manufacturer-specific probe functions */
-struct spi_flash *spi_flash_probe_spansion(struct spi_slave *spi, u8 *idcode);
-struct spi_flash *spi_flash_probe_atmel(struct spi_slave *spi, u8 *idcode);
-struct spi_flash *spi_flash_probe_eon(struct spi_slave *spi, u8 *idcode);
-struct spi_flash *spi_flash_probe_macronix(struct spi_slave *spi, u8 *idcode);
-struct spi_flash *spi_flash_probe_sst(struct spi_slave *spi, u8 *idcode);
-struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 *idcode);
-struct spi_flash *spi_flash_probe_winbond(struct spi_slave *spi, u8 *idcode);
-struct spi_flash *spi_fram_probe_ramtron(struct spi_slave *spi, u8 *idcode);
-struct spi_flash *spi_flash_probe_gigadevice(struct spi_slave *spi, u8 *idcode);
+#endif /* _SPI_FLASH_INTERNAL_H_ */
diff --git a/drivers/mtd/spi/sf_ops.c b/drivers/mtd/spi/sf_ops.c
new file mode 100644
index 0000000..2396e22
--- /dev/null
+++ b/drivers/mtd/spi/sf_ops.c
@@ -0,0 +1,405 @@
+/*
+ * SPI flash operations
+ *
+ * Copyright (C) 2008 Atmel Corporation
+ * Copyright (C) 2010 Reinhard Meyer, EMK Elektronik
+ * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <common.h>
+#include <spi.h>
+#include <spi_flash.h>
+#include <watchdog.h>
+
+#include "sf_internal.h"
+
+static void spi_flash_addr(u32 addr, u8 *cmd)
+{
+	/* cmd[0] is actual command */
+	cmd[1] = addr >> 16;
+	cmd[2] = addr >> 8;
+	cmd[3] = addr >> 0;
+}
+
+int spi_flash_cmd_write_status(struct spi_flash *flash, u8 sr)
+{
+	u8 cmd;
+	int ret;
+
+	cmd = CMD_WRITE_STATUS;
+	ret = spi_flash_write_common(flash, &cmd, 1, &sr, 1);
+	if (ret < 0) {
+		debug("SF: fail to write status register\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_SPI_FLASH_BAR
+static int spi_flash_cmd_bankaddr_write(struct spi_flash *flash, u8 bank_sel)
+{
+	u8 cmd;
+	int ret;
+
+	if (flash->bank_curr == bank_sel) {
+		debug("SF: not require to enable bank%d\n", bank_sel);
+		return 0;
+	}
+
+	cmd = flash->bank_write_cmd;
+	ret = spi_flash_write_common(flash, &cmd, 1, &bank_sel, 1);
+	if (ret < 0) {
+		debug("SF: fail to write bank register\n");
+		return ret;
+	}
+	flash->bank_curr = bank_sel;
+
+	return 0;
+}
+#endif
+
+int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout)
+{
+	struct spi_slave *spi = flash->spi;
+	unsigned long timebase;
+	int ret;
+	u8 status;
+	u8 check_status = 0x0;
+	u8 poll_bit = STATUS_WIP;
+	u8 cmd = flash->poll_cmd;
+
+	if (cmd == CMD_FLAG_STATUS) {
+		poll_bit = STATUS_PEC;
+		check_status = poll_bit;
+	}
+
+	ret = spi_xfer(spi, 8, &cmd, NULL, SPI_XFER_BEGIN);
+	if (ret) {
+		debug("SF: fail to read %s status register\n",
+		      cmd == CMD_READ_STATUS ? "read" : "flag");
+		return ret;
+	}
+
+	timebase = get_timer(0);
+	do {
+		WATCHDOG_RESET();
+
+		ret = spi_xfer(spi, 8, NULL, &status, 0);
+		if (ret)
+			return -1;
+
+		if ((status & poll_bit) == check_status)
+			break;
+
+	} while (get_timer(timebase) < timeout);
+
+	spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END);
+
+	if ((status & poll_bit) == check_status)
+		return 0;
+
+	/* Timed out */
+	debug("SF: time out!\n");
+	return -1;
+}
+
+int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd,
+		size_t cmd_len, const void *buf, size_t buf_len)
+{
+	struct spi_slave *spi = flash->spi;
+	unsigned long timeout = SPI_FLASH_PROG_TIMEOUT;
+	int ret;
+
+	if (buf == NULL)
+		timeout = SPI_FLASH_PAGE_ERASE_TIMEOUT;
+
+	ret = spi_claim_bus(flash->spi);
+	if (ret) {
+		debug("SF: unable to claim SPI bus\n");
+		return ret;
+	}
+
+	ret = spi_flash_cmd_write_enable(flash);
+	if (ret < 0) {
+		debug("SF: enabling write failed\n");
+		return ret;
+	}
+
+	ret = spi_flash_cmd_write(spi, cmd, cmd_len, buf, buf_len);
+	if (ret < 0) {
+		debug("SF: write cmd failed\n");
+		return ret;
+	}
+
+	ret = spi_flash_cmd_wait_ready(flash, timeout);
+	if (ret < 0) {
+		debug("SF: write %s timed out\n",
+		      timeout == SPI_FLASH_PROG_TIMEOUT ?
+			"program" : "page erase");
+		return ret;
+	}
+
+	spi_release_bus(spi);
+
+	return ret;
+}
+
+int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len)
+{
+	u32 erase_size;
+	u8 cmd[4];
+	int ret = -1;
+
+	erase_size = flash->erase_size;
+	if (offset % erase_size || len % erase_size) {
+		debug("SF: Erase offset/length not multiple of erase size\n");
+		return -1;
+	}
+
+	cmd[0] = flash->erase_cmd;
+	while (len) {
+#ifdef CONFIG_SPI_FLASH_BAR
+		u8 bank_sel;
+
+		bank_sel = offset / SPI_FLASH_16MB_BOUN;
+
+		ret = spi_flash_cmd_bankaddr_write(flash, bank_sel);
+		if (ret) {
+			debug("SF: fail to set bank%d\n", bank_sel);
+			return ret;
+		}
+#endif
+		spi_flash_addr(offset, cmd);
+
+		debug("SF: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1],
+		      cmd[2], cmd[3], offset);
+
+		ret = spi_flash_write_common(flash, cmd, sizeof(cmd), NULL, 0);
+		if (ret < 0) {
+			debug("SF: erase failed\n");
+			break;
+		}
+
+		offset += erase_size;
+		len -= erase_size;
+	}
+
+	return ret;
+}
+
+int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset,
+		size_t len, const void *buf)
+{
+	unsigned long byte_addr, page_size;
+	size_t chunk_len, actual;
+	u8 cmd[4];
+	int ret = -1;
+
+	page_size = flash->page_size;
+
+	cmd[0] = CMD_PAGE_PROGRAM;
+	for (actual = 0; actual < len; actual += chunk_len) {
+#ifdef CONFIG_SPI_FLASH_BAR
+		u8 bank_sel;
+
+		bank_sel = offset / SPI_FLASH_16MB_BOUN;
+
+		ret = spi_flash_cmd_bankaddr_write(flash, bank_sel);
+		if (ret) {
+			debug("SF: fail to set bank%d\n", bank_sel);
+			return ret;
+		}
+#endif
+		byte_addr = offset % page_size;
+		chunk_len = min(len - actual, page_size - byte_addr);
+
+		if (flash->spi->max_write_size)
+			chunk_len = min(chunk_len, flash->spi->max_write_size);
+
+		spi_flash_addr(offset, cmd);
+
+		debug("PP: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %zu\n",
+		      buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], chunk_len);
+
+		ret = spi_flash_write_common(flash, cmd, sizeof(cmd),
+					buf + actual, chunk_len);
+		if (ret < 0) {
+			debug("SF: write failed\n");
+			break;
+		}
+
+		offset += chunk_len;
+	}
+
+	return ret;
+}
+
+int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd,
+		size_t cmd_len, void *data, size_t data_len)
+{
+	struct spi_slave *spi = flash->spi;
+	int ret;
+
+	ret = spi_claim_bus(flash->spi);
+	if (ret) {
+		debug("SF: unable to claim SPI bus\n");
+		return ret;
+	}
+
+	ret = spi_flash_cmd_read(spi, cmd, cmd_len, data, data_len);
+	if (ret < 0) {
+		debug("SF: read cmd failed\n");
+		return ret;
+	}
+
+	spi_release_bus(spi);
+
+	return ret;
+}
+
+int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset,
+		size_t len, void *data)
+{
+	u8 cmd[5], bank_sel = 0;
+	u32 remain_len, read_len;
+	int ret = -1;
+
+	/* Handle memory-mapped SPI */
+	if (flash->memory_map) {
+		spi_xfer(flash->spi, 0, NULL, NULL, SPI_XFER_MMAP);
+		memcpy(data, flash->memory_map + offset, len);
+		spi_xfer(flash->spi, 0, NULL, NULL, SPI_XFER_MMAP_END);
+		return 0;
+	}
+
+	cmd[0] = CMD_READ_ARRAY_FAST;
+	cmd[4] = 0x00;
+
+	while (len) {
+#ifdef CONFIG_SPI_FLASH_BAR
+		bank_sel = offset / SPI_FLASH_16MB_BOUN;
+
+		ret = spi_flash_cmd_bankaddr_write(flash, bank_sel);
+		if (ret) {
+			debug("SF: fail to set bank%d\n", bank_sel);
+			return ret;
+		}
+#endif
+		remain_len = (SPI_FLASH_16MB_BOUN * (bank_sel + 1) - offset);
+		if (len < remain_len)
+			read_len = len;
+		else
+			read_len = remain_len;
+
+		spi_flash_addr(offset, cmd);
+
+		ret = spi_flash_read_common(flash, cmd, sizeof(cmd),
+							data, read_len);
+		if (ret < 0) {
+			debug("SF: read failed\n");
+			break;
+		}
+
+		offset += read_len;
+		len -= read_len;
+		data += read_len;
+	}
+
+	return ret;
+}
+
+#ifdef CONFIG_SPI_FLASH_SST
+static int sst_byte_write(struct spi_flash *flash, u32 offset, const void *buf)
+{
+	int ret;
+	u8 cmd[4] = {
+		CMD_SST_BP,
+		offset >> 16,
+		offset >> 8,
+		offset,
+	};
+
+	debug("BP[%02x]: 0x%p => cmd = { 0x%02x 0x%06x }\n",
+	      spi_w8r8(flash->spi, CMD_READ_STATUS), buf, cmd[0], offset);
+
+	ret = spi_flash_cmd_write_enable(flash);
+	if (ret)
+		return ret;
+
+	ret = spi_flash_cmd_write(flash->spi, cmd, sizeof(cmd), buf, 1);
+	if (ret)
+		return ret;
+
+	return spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
+}
+
+int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len,
+		const void *buf)
+{
+	size_t actual, cmd_len;
+	int ret;
+	u8 cmd[4];
+
+	ret = spi_claim_bus(flash->spi);
+	if (ret) {
+		debug("SF: Unable to claim SPI bus\n");
+		return ret;
+	}
+
+	/* If the data is not word aligned, write out leading single byte */
+	actual = offset % 2;
+	if (actual) {
+		ret = sst_byte_write(flash, offset, buf);
+		if (ret)
+			goto done;
+	}
+	offset += actual;
+
+	ret = spi_flash_cmd_write_enable(flash);
+	if (ret)
+		goto done;
+
+	cmd_len = 4;
+	cmd[0] = CMD_SST_AAI_WP;
+	cmd[1] = offset >> 16;
+	cmd[2] = offset >> 8;
+	cmd[3] = offset;
+
+	for (; actual < len - 1; actual += 2) {
+		debug("WP[%02x]: 0x%p => cmd = { 0x%02x 0x%06x }\n",
+		      spi_w8r8(flash->spi, CMD_READ_STATUS), buf + actual,
+		      cmd[0], offset);
+
+		ret = spi_flash_cmd_write(flash->spi, cmd, cmd_len,
+					buf + actual, 2);
+		if (ret) {
+			debug("SF: sst word program failed\n");
+			break;
+		}
+
+		ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
+		if (ret)
+			break;
+
+		cmd_len = 1;
+		offset += 2;
+	}
+
+	if (!ret)
+		ret = spi_flash_cmd_write_disable(flash);
+
+	/* If there is a single trailing byte, write it out */
+	if (!ret && actual != len)
+		ret = sst_byte_write(flash, offset, buf + actual);
+
+ done:
+	debug("SF: sst: program %s %zu bytes @ 0x%zx\n",
+	      ret ? "failure" : "success", len, offset - actual);
+
+	spi_release_bus(flash->spi);
+	return ret;
+}
+#endif
diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c
new file mode 100644
index 0000000..4251b1b
--- /dev/null
+++ b/drivers/mtd/spi/sf_probe.c
@@ -0,0 +1,363 @@
+/*
+ * SPI flash probing
+ *
+ * Copyright (C) 2008 Atmel Corporation
+ * Copyright (C) 2010 Reinhard Meyer, EMK Elektronik
+ * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <common.h>
+#include <fdtdec.h>
+#include <malloc.h>
+#include <spi.h>
+#include <spi_flash.h>
+
+#include "sf_internal.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/**
+ * struct spi_flash_params - SPI/QSPI flash device params structure
+ *
+ * @name:		Device name ([MANUFLETTER][DEVTYPE][DENSITY][EXTRAINFO])
+ * @jedec:		Device jedec ID (0x[1byte_manuf_id][2byte_dev_id])
+ * @ext_jedec:		Device ext_jedec ID
+ * @sector_size:	Sector size of this device
+ * @nr_sectors:	No.of sectors on this device
+ * @flags:		Importent param, for flash specific behaviour
+ */
+struct spi_flash_params {
+	const char *name;
+	u32 jedec;
+	u16 ext_jedec;
+	u32 sector_size;
+	u32 nr_sectors;
+	u16 flags;
+};
+
+static const struct spi_flash_params spi_flash_params_table[] = {
+#ifdef CONFIG_SPI_FLASH_ATMEL		/* ATMEL */
+	{"AT45DB011D",	   0x1f2200, 0x0,	64 * 1024,     4,	       SECT_4K},
+	{"AT45DB021D",	   0x1f2300, 0x0,	64 * 1024,     8,	       SECT_4K},
+	{"AT45DB041D",	   0x1f2400, 0x0,	64 * 1024,     8,	       SECT_4K},
+	{"AT45DB081D",	   0x1f2500, 0x0,	64 * 1024,    16,	       SECT_4K},
+	{"AT45DB161D",	   0x1f2600, 0x0,	64 * 1024,    32,	       SECT_4K},
+	{"AT45DB321D",	   0x1f2700, 0x0,	64 * 1024,    64,	       SECT_4K},
+	{"AT45DB641D",	   0x1f2800, 0x0,	64 * 1024,   128,	       SECT_4K},
+#endif
+#ifdef CONFIG_SPI_FLASH_EON		/* EON */
+	{"EN25Q32B",	   0x1c3016, 0x0,	64 * 1024,    64,	             0},
+	{"EN25Q64",	   0x1c3017, 0x0,	64 * 1024,   128,	       SECT_4K},
+	{"EN25Q128B",	   0x1c3018, 0x0,       64 * 1024,   256,	             0},
+	{"EN25S64",	   0x1c3817, 0x0,	64 * 1024,   128,		     0},
+#endif
+#ifdef CONFIG_SPI_FLASH_GIGADEVICE	/* GIGADEVICE */
+	{"GD25Q64B",	   0xc84017, 0x0,	64 * 1024,   128,	       SECT_4K},
+	{"GD25LQ32",	   0xc86016, 0x0,	64 * 1024,    64,	       SECT_4K},
+#endif
+#ifdef CONFIG_SPI_FLASH_MACRONIX	/* MACRONIX */
+	{"MX25L4005",	   0xc22013, 0x0,	64 * 1024,     8,	             0},
+	{"MX25L8005",	   0xc22014, 0x0,	64 * 1024,    16,	             0},
+	{"MX25L1605D",	   0xc22015, 0x0,	64 * 1024,    32,	             0},
+	{"MX25L3205D",	   0xc22016, 0x0,	64 * 1024,    64,	             0},
+	{"MX25L6405D",	   0xc22017, 0x0,	64 * 1024,   128,	             0},
+	{"MX25L12805",	   0xc22018, 0x0,	64 * 1024,   256,	             0},
+	{"MX25L25635F",	   0xc22019, 0x0,	64 * 1024,   512,	             0},
+	{"MX25L51235F",	   0xc2201A, 0x0,	64 * 1024,  1024,	             0},
+	{"MX25L12855E",	   0xc22618, 0x0,	64 * 1024,   256,	             0},
+#endif
+#ifdef CONFIG_SPI_FLASH_SPANSION	/* SPANSION */
+	{"S25FL008A",	   0x010213, 0x0,	64 * 1024,    16,	             0},
+	{"S25FL016A",	   0x010214, 0x0,	64 * 1024,    32,	             0},
+	{"S25FL032A",	   0x010215, 0x0,	64 * 1024,    64,	             0},
+	{"S25FL064A",	   0x010216, 0x0,	64 * 1024,   128,	             0},
+	{"S25FL128P_256K", 0x012018, 0x0300,   256 * 1024,    64,	             0},
+	{"S25FL128P_64K",  0x012018, 0x0301,    64 * 1024,   256,	             0},
+	{"S25FL032P",	   0x010215, 0x4d00,    64 * 1024,    64,	             0},
+	{"S25FL064P",	   0x010216, 0x4d00,    64 * 1024,   128,	             0},
+	{"S25FL128S_64K",  0x012018, 0x4d01,    64 * 1024,   256,		     0},
+	{"S25FL256S_256K", 0x010219, 0x4d00,    64 * 1024,   512,	             0},
+	{"S25FL256S_64K",  0x010219, 0x4d01,    64 * 1024,   512,	             0},
+	{"S25FL512S_256K", 0x010220, 0x4d00,    64 * 1024,  1024,	             0},
+	{"S25FL512S_64K",  0x010220, 0x4d01,    64 * 1024,  1024,	             0},
+#endif
+#ifdef CONFIG_SPI_FLASH_STMICRO		/* STMICRO */
+	{"M25P10",	   0x202011, 0x0,       32 * 1024,     4,	             0},
+	{"M25P20",	   0x202012, 0x0,       64 * 1024,     4,	             0},
+	{"M25P40",	   0x202013, 0x0,       64 * 1024,     8,	             0},
+	{"M25P80",	   0x202014, 0x0,       64 * 1024,    16,	             0},
+	{"M25P16",	   0x202015, 0x0,       64 * 1024,    32,	             0},
+	{"M25P32",	   0x202016, 0x0,       64 * 1024,    64,	             0},
+	{"M25P64",	   0x202017, 0x0,       64 * 1024,   128,	             0},
+	{"M25P128",	   0x202018, 0x0,      256 * 1024,    64,	             0},
+	{"N25Q32",	   0x20ba16, 0x0,       64 * 1024,    64,	       SECT_4K},
+	{"N25Q32A",	   0x20bb16, 0x0,       64 * 1024,    64,	       SECT_4K},
+	{"N25Q64",	   0x20ba17, 0x0,       64 * 1024,   128,	       SECT_4K},
+	{"N25Q64A",	   0x20bb17, 0x0,       64 * 1024,   128,	       SECT_4K},
+	{"N25Q128",	   0x20ba18, 0x0,       64 * 1024,   256,	       SECT_4K},
+	{"N25Q128A",	   0x20bb18, 0x0,       64 * 1024,   256,	       SECT_4K},
+	{"N25Q256",	   0x20ba19, 0x0,       64 * 1024,   512,	       SECT_4K},
+	{"N25Q256A",	   0x20bb19, 0x0,       64 * 1024,   512,	       SECT_4K},
+	{"N25Q512",	   0x20ba20, 0x0,       64 * 1024,  1024,      E_FSR | SECT_4K},
+	{"N25Q512A",	   0x20bb20, 0x0,       64 * 1024,  1024,      E_FSR | SECT_4K},
+	{"N25Q1024",	   0x20ba21, 0x0,       64 * 1024,  2048,      E_FSR | SECT_4K},
+	{"N25Q1024A",	   0x20bb21, 0x0,       64 * 1024,  2048,      E_FSR | SECT_4K},
+#endif
+#ifdef CONFIG_SPI_FLASH_SST		/* SST */
+	{"SST25VF040B",	   0xbf258d, 0x0,	64 * 1024,     8,     SECT_4K | SST_WP},
+	{"SST25VF080B",	   0xbf258e, 0x0,	64 * 1024,    16,     SECT_4K | SST_WP},
+	{"SST25VF016B",	   0xbf2541, 0x0,	64 * 1024,    32,     SECT_4K | SST_WP},
+	{"SST25VF032B",	   0xbf254a, 0x0,	64 * 1024,    64,     SECT_4K | SST_WP},
+	{"SST25VF064C",	   0xbf254b, 0x0,	64 * 1024,   128,	       SECT_4K},
+	{"SST25WF512",	   0xbf2501, 0x0,	64 * 1024,     1,     SECT_4K | SST_WP},
+	{"SST25WF010",	   0xbf2502, 0x0,	64 * 1024,     2,     SECT_4K | SST_WP},
+	{"SST25WF020",	   0xbf2503, 0x0,	64 * 1024,     4,     SECT_4K | SST_WP},
+	{"SST25WF040",	   0xbf2504, 0x0,	64 * 1024,     8,     SECT_4K | SST_WP},
+	{"SST25WF080",	   0xbf2505, 0x0,	64 * 1024,    16,     SECT_4K | SST_WP},
+#endif
+#ifdef CONFIG_SPI_FLASH_WINBOND		/* WINBOND */
+	{"W25P80",	   0xef2014, 0x0,	64 * 1024,    16,		    0},
+	{"W25P16",	   0xef2015, 0x0,	64 * 1024,    32,		    0},
+	{"W25P32",	   0xef2016, 0x0,	64 * 1024,    64,		    0},
+	{"W25X40",	   0xef3013, 0x0,	64 * 1024,     8,	      SECT_4K},
+	{"W25X16",	   0xef3015, 0x0,	64 * 1024,    32,	      SECT_4K},
+	{"W25X32",	   0xef3016, 0x0,	64 * 1024,    64,	      SECT_4K},
+	{"W25X64",	   0xef3017, 0x0,	64 * 1024,   128,	      SECT_4K},
+	{"W25Q80BL",	   0xef4014, 0x0,	64 * 1024,    16,	      SECT_4K},
+	{"W25Q16CL",	   0xef4015, 0x0,	64 * 1024,    32,	      SECT_4K},
+	{"W25Q32BV",	   0xef4016, 0x0,	64 * 1024,    64,	      SECT_4K},
+	{"W25Q64CV",	   0xef4017, 0x0,	64 * 1024,   128,	      SECT_4K},
+	{"W25Q128BV",	   0xef4018, 0x0,	64 * 1024,   256,	      SECT_4K},
+	{"W25Q256",	   0xef4019, 0x0,	64 * 1024,   512,	      SECT_4K},
+	{"W25Q80BW",	   0xef5014, 0x0,	64 * 1024,    16,	      SECT_4K},
+	{"W25Q16DW",	   0xef6015, 0x0,	64 * 1024,    32,	      SECT_4K},
+	{"W25Q32DW",	   0xef6016, 0x0,	64 * 1024,    64,	      SECT_4K},
+	{"W25Q64DW",	   0xef6017, 0x0,	64 * 1024,   128,	      SECT_4K},
+	{"W25Q128FW",	   0xef6018, 0x0,	64 * 1024,   256,	      SECT_4K},
+#endif
+	/*
+	 * Note:
+	 * Below paired flash devices has similar spi_flash_params params.
+	 * (S25FL129P_64K, S25FL128S_64K)
+	 * (W25Q80BL, W25Q80BV)
+	 * (W25Q16CL, W25Q16DV)
+	 * (W25Q32BV, W25Q32FV_SPI)
+	 * (W25Q64CV, W25Q64FV_SPI)
+	 * (W25Q128BV, W25Q128FV_SPI)
+	 * (W25Q32DW, W25Q32FV_QPI)
+	 * (W25Q64DW, W25Q64FV_QPI)
+	 * (W25Q128FW, W25Q128FV_QPI)
+	 */
+};
+
+static struct spi_flash *spi_flash_validate_params(struct spi_slave *spi,
+		u8 *idcode)
+{
+	const struct spi_flash_params *params;
+	struct spi_flash *flash;
+	int i;
+	u16 jedec = idcode[1] << 8 | idcode[2];
+	u16 ext_jedec = idcode[3] << 8 | idcode[4];
+
+	/* Get the flash id (jedec = manuf_id + dev_id, ext_jedec) */
+	for (i = 0; i < ARRAY_SIZE(spi_flash_params_table); i++) {
+		params = &spi_flash_params_table[i];
+		if ((params->jedec >> 16) == idcode[0]) {
+			if ((params->jedec & 0xFFFF) == jedec) {
+				if (params->ext_jedec == 0)
+					break;
+				else if (params->ext_jedec == ext_jedec)
+					break;
+			}
+		}
+	}
+
+	if (i == ARRAY_SIZE(spi_flash_params_table)) {
+		printf("SF: Unsupported flash IDs: ");
+		printf("manuf %02x, jedec %04x, ext_jedec %04x\n",
+		       idcode[0], jedec, ext_jedec);
+		return NULL;
+	}
+
+	flash = malloc(sizeof(*flash));
+	if (!flash) {
+		debug("SF: Failed to allocate spi_flash\n");
+		return NULL;
+	}
+	memset(flash, '\0', sizeof(*flash));
+
+	flash->spi = spi;
+	flash->name = params->name;
+	flash->memory_map = spi->memory_map;
+
+	/* Assign spi_flash ops */
+	flash->write = spi_flash_cmd_write_ops;
+#ifdef CONFIG_SPI_FLASH_SST
+	if (params->flags & SST_WP)
+		flash->write = sst_write_wp;
+#endif
+	flash->erase = spi_flash_cmd_erase_ops;
+	flash->read = spi_flash_cmd_read_ops;
+
+	/* Compute the flash size */
+	flash->page_size = (ext_jedec == 0x4d00) ? 512 : 256;
+	flash->sector_size = params->sector_size;
+	flash->size = flash->sector_size * params->nr_sectors;
+
+	/* Compute erase sector and command */
+	if (params->flags & SECT_4K) {
+		flash->erase_cmd = CMD_ERASE_4K;
+		flash->erase_size = 4096;
+	} else if (params->flags & SECT_32K) {
+		flash->erase_cmd = CMD_ERASE_32K;
+		flash->erase_size = 32768;
+	} else {
+		flash->erase_cmd = CMD_ERASE_64K;
+		flash->erase_size = flash->sector_size;
+	}
+
+	/* Poll cmd seclection */
+	flash->poll_cmd = CMD_READ_STATUS;
+#ifdef CONFIG_SPI_FLASH_STMICRO
+	if (params->flags & E_FSR)
+		flash->poll_cmd = CMD_FLAG_STATUS;
+#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) {
+		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;
+
+		if (spi_flash_read_common(flash, &flash->bank_read_cmd, 1,
+					  &curr_bank, 1)) {
+			debug("SF: fail to read bank addr register\n");
+			return NULL;
+		}
+		flash->bank_curr = curr_bank;
+	} else {
+		flash->bank_curr = curr_bank;
+	}
+#endif
+
+	/* Flash powers up read-only, so clear BP# bits */
+#if defined(CONFIG_SPI_FLASH_ATMEL) || \
+	defined(CONFIG_SPI_FLASH_MACRONIX) || \
+	defined(CONFIG_SPI_FLASH_SST)
+		spi_flash_cmd_write_status(flash, 0);
+#endif
+
+	return flash;
+}
+
+#ifdef CONFIG_OF_CONTROL
+int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash)
+{
+	fdt_addr_t addr;
+	fdt_size_t size;
+	int node;
+
+	/* If there is no node, do nothing */
+	node = fdtdec_next_compatible(blob, 0, COMPAT_GENERIC_SPI_FLASH);
+	if (node < 0)
+		return 0;
+
+	addr = fdtdec_get_addr_size(blob, node, "memory-map", &size);
+	if (addr == FDT_ADDR_T_NONE) {
+		debug("%s: Cannot decode address\n", __func__);
+		return 0;
+	}
+
+	if (flash->size != size) {
+		debug("%s: Memory map must cover entire device\n", __func__);
+		return -1;
+	}
+	flash->memory_map = (void *)addr;
+
+	return 0;
+}
+#endif /* CONFIG_OF_CONTROL */
+
+struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
+		unsigned int max_hz, unsigned int spi_mode)
+{
+	struct spi_slave *spi;
+	struct spi_flash *flash = NULL;
+	u8 idcode[5];
+	int ret;
+
+	/* Setup spi_slave */
+	spi = spi_setup_slave(bus, cs, max_hz, spi_mode);
+	if (!spi) {
+		printf("SF: Failed to set up slave\n");
+		return NULL;
+	}
+
+	/* Claim spi bus */
+	ret = spi_claim_bus(spi);
+	if (ret) {
+		debug("SF: Failed to claim SPI bus: %d\n", ret);
+		goto err_claim_bus;
+	}
+
+	/* Read the ID codes */
+	ret = spi_flash_cmd(spi, CMD_READ_ID, idcode, sizeof(idcode));
+	if (ret) {
+		printf("SF: Failed to get idcodes\n");
+		goto err_read_id;
+	}
+
+#ifdef DEBUG
+	printf("SF: Got idcodes\n");
+	print_buffer(0, idcode, 1, sizeof(idcode), 0);
+#endif
+
+	/* Validate params from spi_flash_params table */
+	flash = spi_flash_validate_params(spi, idcode);
+	if (!flash)
+		goto err_read_id;
+
+#ifdef CONFIG_OF_CONTROL
+	if (spi_flash_decode_fdt(gd->fdt_blob, flash)) {
+		debug("SF: FDT decode error\n");
+		goto err_read_id;
+	}
+#endif
+#ifndef CONFIG_SPL_BUILD
+	printf("SF: Detected %s with page size ", flash->name);
+	print_size(flash->page_size, ", erase size ");
+	print_size(flash->erase_size, ", total ");
+	print_size(flash->size, "");
+	if (flash->memory_map)
+		printf(", mapped at %p", flash->memory_map);
+	puts("\n");
+#endif
+#ifndef CONFIG_SPI_FLASH_BAR
+	if (flash->size > SPI_FLASH_16MB_BOUN) {
+		puts("SF: Warning - Only lower 16MiB accessible,");
+		puts(" Full access #define CONFIG_SPI_FLASH_BAR\n");
+	}
+#endif
+
+	/* Release spi bus */
+	spi_release_bus(spi);
+
+	return flash;
+
+err_read_id:
+	spi_release_bus(spi);
+err_claim_bus:
+	spi_free_slave(spi);
+	return NULL;
+}
+
+void spi_flash_free(struct spi_flash *flash)
+{
+	spi_free_slave(flash->spi);
+	free(flash);
+}
diff --git a/drivers/mtd/spi/spansion.c b/drivers/mtd/spi/spansion.c
deleted file mode 100644
index fa7ac8c..0000000
--- a/drivers/mtd/spi/spansion.c
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (C) 2009 Freescale Semiconductor, Inc.
- *
- * Author: Mingkai Hu (Mingkai.hu@freescale.com)
- * Based on stmicro.c by Wolfgang Denk (wd@denx.de),
- * TsiChung Liew (Tsi-Chung.Liew@freescale.com),
- * and  Jason McMullan (mcmullan@netapp.com)
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <common.h>
-#include <malloc.h>
-#include <spi_flash.h>
-
-#include "spi_flash_internal.h"
-
-struct spansion_spi_flash_params {
-	u16 idcode1;
-	u16 idcode2;
-	u16 pages_per_sector;
-	u16 nr_sectors;
-	const char *name;
-};
-
-static const struct spansion_spi_flash_params spansion_spi_flash_table[] = {
-	{
-		.idcode1 = 0x0213,
-		.idcode2 = 0,
-		.pages_per_sector = 256,
-		.nr_sectors = 16,
-		.name = "S25FL008A",
-	},
-	{
-		.idcode1 = 0x0214,
-		.idcode2 = 0,
-		.pages_per_sector = 256,
-		.nr_sectors = 32,
-		.name = "S25FL016A",
-	},
-	{
-		.idcode1 = 0x0215,
-		.idcode2 = 0,
-		.pages_per_sector = 256,
-		.nr_sectors = 64,
-		.name = "S25FL032A",
-	},
-	{
-		.idcode1 = 0x0216,
-		.idcode2 = 0,
-		.pages_per_sector = 256,
-		.nr_sectors = 128,
-		.name = "S25FL064A",
-	},
-	{
-		.idcode1 = 0x2018,
-		.idcode2 = 0x0301,
-		.pages_per_sector = 256,
-		.nr_sectors = 256,
-		.name = "S25FL128P_64K",
-	},
-	{
-		.idcode1 = 0x2018,
-		.idcode2 = 0x0300,
-		.pages_per_sector = 1024,
-		.nr_sectors = 64,
-		.name = "S25FL128P_256K",
-	},
-	{
-		.idcode1 = 0x0215,
-		.idcode2 = 0x4d00,
-		.pages_per_sector = 256,
-		.nr_sectors = 64,
-		.name = "S25FL032P",
-	},
-	{
-		.idcode1 = 0x0216,
-		.idcode2 = 0x4d00,
-		.pages_per_sector = 256,
-		.nr_sectors = 128,
-		.name = "S25FL064P",
-	},
-	{
-		.idcode1 = 0x2018,
-		.idcode2 = 0x4d01,
-		.pages_per_sector = 256,
-		.nr_sectors = 256,
-		.name = "S25FL129P_64K/S25FL128S_64K",
-	},
-	{
-		.idcode1 = 0x0219,
-		.idcode2 = 0x4d01,
-		.pages_per_sector = 256,
-		.nr_sectors = 512,
-		.name = "S25FL256S_64K",
-	},
-	{
-		.idcode1 = 0x0220,
-		.idcode2 = 0x4d01,
-		.pages_per_sector = 256,
-		.nr_sectors = 1024,
-		.name = "S25FL512S_64K",
-	},
-};
-
-struct spi_flash *spi_flash_probe_spansion(struct spi_slave *spi, u8 *idcode)
-{
-	const struct spansion_spi_flash_params *params;
-	struct spi_flash *flash;
-	unsigned int i;
-	unsigned short jedec, ext_jedec;
-
-	jedec = idcode[1] << 8 | idcode[2];
-	ext_jedec = idcode[3] << 8 | idcode[4];
-
-	for (i = 0; i < ARRAY_SIZE(spansion_spi_flash_table); i++) {
-		params = &spansion_spi_flash_table[i];
-		if (params->idcode1 == jedec) {
-			if (params->idcode2 == ext_jedec)
-				break;
-		}
-	}
-
-	if (i == ARRAY_SIZE(spansion_spi_flash_table)) {
-		debug("SF: Unsupported SPANSION ID %04x %04x\n",
-		      jedec, ext_jedec);
-		return NULL;
-	}
-
-	flash = spi_flash_alloc_base(spi, params->name);
-	if (!flash) {
-		debug("SF: Failed to allocate memory\n");
-		return NULL;
-	}
-
-	flash->page_size = 256;
-	flash->sector_size = 256 * params->pages_per_sector;
-	flash->size = flash->sector_size * params->nr_sectors;
-
-	return flash;
-}
diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
deleted file mode 100644
index 5d5055f..0000000
--- a/drivers/mtd/spi/spi_flash.c
+++ /dev/null
@@ -1,615 +0,0 @@
-/*
- * SPI flash interface
- *
- * Copyright (C) 2008 Atmel Corporation
- * Copyright (C) 2010 Reinhard Meyer, EMK Elektronik
- *
- * Licensed under the GPL-2 or later.
- */
-
-#include <common.h>
-#include <fdtdec.h>
-#include <malloc.h>
-#include <spi.h>
-#include <spi_flash.h>
-#include <watchdog.h>
-
-#include "spi_flash_internal.h"
-
-DECLARE_GLOBAL_DATA_PTR;
-
-static void spi_flash_addr(u32 addr, u8 *cmd)
-{
-	/* cmd[0] is actual command */
-	cmd[1] = addr >> 16;
-	cmd[2] = addr >> 8;
-	cmd[3] = addr >> 0;
-}
-
-static int spi_flash_read_write(struct spi_slave *spi,
-				const u8 *cmd, size_t cmd_len,
-				const u8 *data_out, u8 *data_in,
-				size_t data_len)
-{
-	unsigned long flags = SPI_XFER_BEGIN;
-	int ret;
-
-	if (data_len == 0)
-		flags |= SPI_XFER_END;
-
-	ret = spi_xfer(spi, cmd_len * 8, cmd, NULL, flags);
-	if (ret) {
-		debug("SF: Failed to send command (%zu bytes): %d\n",
-		      cmd_len, ret);
-	} else if (data_len != 0) {
-		ret = spi_xfer(spi, data_len * 8, data_out, data_in,
-					SPI_XFER_END);
-		if (ret)
-			debug("SF: Failed to transfer %zu bytes of data: %d\n",
-			      data_len, ret);
-	}
-
-	return ret;
-}
-
-int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len)
-{
-	return spi_flash_cmd_read(spi, &cmd, 1, response, len);
-}
-
-int spi_flash_cmd_read(struct spi_slave *spi, const u8 *cmd,
-		size_t cmd_len, void *data, size_t data_len)
-{
-	return spi_flash_read_write(spi, cmd, cmd_len, NULL, data, data_len);
-}
-
-int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len,
-		const void *data, size_t data_len)
-{
-	return spi_flash_read_write(spi, cmd, cmd_len, data, NULL, data_len);
-}
-
-int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout)
-{
-	struct spi_slave *spi = flash->spi;
-	unsigned long timebase;
-	int ret;
-	u8 status;
-	u8 check_status = 0x0;
-	u8 poll_bit = STATUS_WIP;
-	u8 cmd = flash->poll_cmd;
-
-	if (cmd == CMD_FLAG_STATUS) {
-		poll_bit = STATUS_PEC;
-		check_status = poll_bit;
-	}
-
-	ret = spi_xfer(spi, 8, &cmd, NULL, SPI_XFER_BEGIN);
-	if (ret) {
-		debug("SF: fail to read %s status register\n",
-		      cmd == CMD_READ_STATUS ? "read" : "flag");
-		return ret;
-	}
-
-	timebase = get_timer(0);
-	do {
-		WATCHDOG_RESET();
-
-		ret = spi_xfer(spi, 8, NULL, &status, 0);
-		if (ret)
-			return -1;
-
-		if ((status & poll_bit) == check_status)
-			break;
-
-	} while (get_timer(timebase) < timeout);
-
-	spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END);
-
-	if ((status & poll_bit) == check_status)
-		return 0;
-
-	/* Timed out */
-	debug("SF: time out!\n");
-	return -1;
-}
-
-int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd,
-		size_t cmd_len, const void *buf, size_t buf_len)
-{
-	struct spi_slave *spi = flash->spi;
-	unsigned long timeout = SPI_FLASH_PROG_TIMEOUT;
-	int ret;
-
-	if (buf == NULL)
-		timeout = SPI_FLASH_PAGE_ERASE_TIMEOUT;
-
-	ret = spi_claim_bus(flash->spi);
-	if (ret) {
-		debug("SF: unable to claim SPI bus\n");
-		return ret;
-	}
-
-	ret = spi_flash_cmd_write_enable(flash);
-	if (ret < 0) {
-		debug("SF: enabling write failed\n");
-		return ret;
-	}
-
-	ret = spi_flash_cmd_write(spi, cmd, cmd_len, buf, buf_len);
-	if (ret < 0) {
-		debug("SF: write cmd failed\n");
-		return ret;
-	}
-
-	ret = spi_flash_cmd_wait_ready(flash, timeout);
-	if (ret < 0) {
-		debug("SF: write %s timed out\n",
-		      timeout == SPI_FLASH_PROG_TIMEOUT ?
-			"program" : "page erase");
-		return ret;
-	}
-
-	spi_release_bus(spi);
-
-	return ret;
-}
-
-int spi_flash_cmd_erase(struct spi_flash *flash, u32 offset, size_t len)
-{
-	u32 erase_size;
-	u8 cmd[4];
-	int ret = -1;
-
-	erase_size = flash->sector_size;
-	if (offset % erase_size || len % erase_size) {
-		debug("SF: Erase offset/length not multiple of erase size\n");
-		return -1;
-	}
-
-	if (erase_size == 4096)
-		cmd[0] = CMD_ERASE_4K;
-	else
-		cmd[0] = CMD_ERASE_64K;
-
-	while (len) {
-#ifdef CONFIG_SPI_FLASH_BAR
-		u8 bank_sel;
-
-		bank_sel = offset / SPI_FLASH_16MB_BOUN;
-
-		ret = spi_flash_cmd_bankaddr_write(flash, bank_sel);
-		if (ret) {
-			debug("SF: fail to set bank%d\n", bank_sel);
-			return ret;
-		}
-#endif
-		spi_flash_addr(offset, cmd);
-
-		debug("SF: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1],
-		      cmd[2], cmd[3], offset);
-
-		ret = spi_flash_write_common(flash, cmd, sizeof(cmd), NULL, 0);
-		if (ret < 0) {
-			debug("SF: erase failed\n");
-			break;
-		}
-
-		offset += erase_size;
-		len -= erase_size;
-	}
-
-	return ret;
-}
-
-int spi_flash_cmd_write_multi(struct spi_flash *flash, u32 offset,
-		size_t len, const void *buf)
-{
-	unsigned long byte_addr, page_size;
-	size_t chunk_len, actual;
-	u8 cmd[4];
-	int ret = -1;
-
-	page_size = flash->page_size;
-
-	cmd[0] = CMD_PAGE_PROGRAM;
-	for (actual = 0; actual < len; actual += chunk_len) {
-#ifdef CONFIG_SPI_FLASH_BAR
-		u8 bank_sel;
-
-		bank_sel = offset / SPI_FLASH_16MB_BOUN;
-
-		ret = spi_flash_cmd_bankaddr_write(flash, bank_sel);
-		if (ret) {
-			debug("SF: fail to set bank%d\n", bank_sel);
-			return ret;
-		}
-#endif
-		byte_addr = offset % page_size;
-		chunk_len = min(len - actual, page_size - byte_addr);
-
-		if (flash->spi->max_write_size)
-			chunk_len = min(chunk_len, flash->spi->max_write_size);
-
-		spi_flash_addr(offset, cmd);
-
-		debug("PP: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %zu\n",
-		      buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], chunk_len);
-
-		ret = spi_flash_write_common(flash, cmd, sizeof(cmd),
-					buf + actual, chunk_len);
-		if (ret < 0) {
-			debug("SF: write failed\n");
-			break;
-		}
-
-		offset += chunk_len;
-	}
-
-	return ret;
-}
-
-int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd,
-		size_t cmd_len, void *data, size_t data_len)
-{
-	struct spi_slave *spi = flash->spi;
-	int ret;
-
-	ret = spi_claim_bus(flash->spi);
-	if (ret) {
-		debug("SF: unable to claim SPI bus\n");
-		return ret;
-	}
-
-	ret = spi_flash_cmd_read(spi, cmd, cmd_len, data, data_len);
-	if (ret < 0) {
-		debug("SF: read cmd failed\n");
-		return ret;
-	}
-
-	spi_release_bus(spi);
-
-	return ret;
-}
-
-int spi_flash_cmd_read_fast(struct spi_flash *flash, u32 offset,
-		size_t len, void *data)
-{
-	u8 cmd[5], bank_sel = 0;
-	u32 remain_len, read_len;
-	int ret = -1;
-
-	/* Handle memory-mapped SPI */
-	if (flash->memory_map) {
-		memcpy(data, flash->memory_map + offset, len);
-		return 0;
-	}
-
-	cmd[0] = CMD_READ_ARRAY_FAST;
-	cmd[4] = 0x00;
-
-	while (len) {
-#ifdef CONFIG_SPI_FLASH_BAR
-		bank_sel = offset / SPI_FLASH_16MB_BOUN;
-
-		ret = spi_flash_cmd_bankaddr_write(flash, bank_sel);
-		if (ret) {
-			debug("SF: fail to set bank%d\n", bank_sel);
-			return ret;
-		}
-#endif
-		remain_len = (SPI_FLASH_16MB_BOUN * (bank_sel + 1) - offset);
-		if (len < remain_len)
-			read_len = len;
-		else
-			read_len = remain_len;
-
-		spi_flash_addr(offset, cmd);
-
-		ret = spi_flash_read_common(flash, cmd, sizeof(cmd),
-							data, read_len);
-		if (ret < 0) {
-			debug("SF: read failed\n");
-			break;
-		}
-
-		offset += read_len;
-		len -= read_len;
-		data += read_len;
-	}
-
-	return ret;
-}
-
-int spi_flash_cmd_write_status(struct spi_flash *flash, u8 sr)
-{
-	u8 cmd;
-	int ret;
-
-	cmd = CMD_WRITE_STATUS;
-	ret = spi_flash_write_common(flash, &cmd, 1, &sr, 1);
-	if (ret < 0) {
-		debug("SF: fail to write status register\n");
-		return ret;
-	}
-
-	return 0;
-}
-
-#ifdef CONFIG_SPI_FLASH_BAR
-int spi_flash_cmd_bankaddr_write(struct spi_flash *flash, u8 bank_sel)
-{
-	u8 cmd;
-	int ret;
-
-	if (flash->bank_curr == bank_sel) {
-		debug("SF: not require to enable bank%d\n", bank_sel);
-		return 0;
-	}
-
-	cmd = flash->bank_write_cmd;
-	ret = spi_flash_write_common(flash, &cmd, 1, &bank_sel, 1);
-	if (ret < 0) {
-		debug("SF: fail to write bank register\n");
-		return ret;
-	}
-	flash->bank_curr = bank_sel;
-
-	return 0;
-}
-
-int spi_flash_bank_config(struct spi_flash *flash, u8 idcode0)
-{
-	u8 cmd;
-	u8 curr_bank = 0;
-
-	/* discover bank cmds */
-	switch (idcode0) {
-	case SPI_FLASH_SPANSION_IDCODE0:
-		flash->bank_read_cmd = CMD_BANKADDR_BRRD;
-		flash->bank_write_cmd = CMD_BANKADDR_BRWR;
-		break;
-	case SPI_FLASH_STMICRO_IDCODE0:
-	case SPI_FLASH_WINBOND_IDCODE0:
-		flash->bank_read_cmd = CMD_EXTNADDR_RDEAR;
-		flash->bank_write_cmd = CMD_EXTNADDR_WREAR;
-		break;
-	default:
-		printf("SF: Unsupported bank commands %02x\n", idcode0);
-		return -1;
-	}
-
-	/* read the bank reg - on which bank the flash is in currently */
-	cmd = flash->bank_read_cmd;
-	if (flash->size > SPI_FLASH_16MB_BOUN) {
-		if (spi_flash_read_common(flash, &cmd, 1, &curr_bank, 1)) {
-			debug("SF: fail to read bank addr register\n");
-			return -1;
-		}
-		flash->bank_curr = curr_bank;
-	} else {
-		flash->bank_curr = curr_bank;
-	}
-
-	return 0;
-}
-#endif
-
-#ifdef CONFIG_OF_CONTROL
-int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash)
-{
-	fdt_addr_t addr;
-	fdt_size_t size;
-	int node;
-
-	/* If there is no node, do nothing */
-	node = fdtdec_next_compatible(blob, 0, COMPAT_GENERIC_SPI_FLASH);
-	if (node < 0)
-		return 0;
-
-	addr = fdtdec_get_addr_size(blob, node, "memory-map", &size);
-	if (addr == FDT_ADDR_T_NONE) {
-		debug("%s: Cannot decode address\n", __func__);
-		return 0;
-	}
-
-	if (flash->size != size) {
-		debug("%s: Memory map must cover entire device\n", __func__);
-		return -1;
-	}
-	flash->memory_map = (void *)addr;
-
-	return 0;
-}
-#endif /* CONFIG_OF_CONTROL */
-
-/*
- * The following table holds all device probe functions
- *
- * shift:  number of continuation bytes before the ID
- * idcode: the expected IDCODE or 0xff for non JEDEC devices
- * probe:  the function to call
- *
- * Non JEDEC devices should be ordered in the table such that
- * the probe functions with best detection algorithms come first.
- *
- * Several matching entries are permitted, they will be tried
- * in sequence until a probe function returns non NULL.
- *
- * IDCODE_CONT_LEN may be redefined if a device needs to declare a
- * larger "shift" value.  IDCODE_PART_LEN generally shouldn't be
- * changed.  This is the max number of bytes probe functions may
- * examine when looking up part-specific identification info.
- *
- * Probe functions will be given the idcode buffer starting at their
- * manu id byte (the "idcode" in the table below).  In other words,
- * all of the continuation bytes will be skipped (the "shift" below).
- */
-#define IDCODE_CONT_LEN 0
-#define IDCODE_PART_LEN 5
-static const struct {
-	const u8 shift;
-	const u8 idcode;
-	struct spi_flash *(*probe) (struct spi_slave *spi, u8 *idcode);
-} flashes[] = {
-	/* Keep it sorted by define name */
-#ifdef CONFIG_SPI_FLASH_ATMEL
-	{ 0, 0x1f, spi_flash_probe_atmel, },
-#endif
-#ifdef CONFIG_SPI_FLASH_EON
-	{ 0, 0x1c, spi_flash_probe_eon, },
-#endif
-#ifdef CONFIG_SPI_FLASH_GIGADEVICE
-	{ 0, 0xc8, spi_flash_probe_gigadevice, },
-#endif
-#ifdef CONFIG_SPI_FLASH_MACRONIX
-	{ 0, 0xc2, spi_flash_probe_macronix, },
-#endif
-#ifdef CONFIG_SPI_FLASH_SPANSION
-	{ 0, 0x01, spi_flash_probe_spansion, },
-#endif
-#ifdef CONFIG_SPI_FLASH_SST
-	{ 0, 0xbf, spi_flash_probe_sst, },
-#endif
-#ifdef CONFIG_SPI_FLASH_STMICRO
-	{ 0, 0x20, spi_flash_probe_stmicro, },
-#endif
-#ifdef CONFIG_SPI_FLASH_WINBOND
-	{ 0, 0xef, spi_flash_probe_winbond, },
-#endif
-#ifdef CONFIG_SPI_FRAM_RAMTRON
-	{ 6, 0xc2, spi_fram_probe_ramtron, },
-# undef IDCODE_CONT_LEN
-# define IDCODE_CONT_LEN 6
-#endif
-	/* Keep it sorted by best detection */
-#ifdef CONFIG_SPI_FLASH_STMICRO
-	{ 0, 0xff, spi_flash_probe_stmicro, },
-#endif
-#ifdef CONFIG_SPI_FRAM_RAMTRON_NON_JEDEC
-	{ 0, 0xff, spi_fram_probe_ramtron, },
-#endif
-};
-#define IDCODE_LEN (IDCODE_CONT_LEN + IDCODE_PART_LEN)
-
-struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
-		unsigned int max_hz, unsigned int spi_mode)
-{
-	struct spi_slave *spi;
-	struct spi_flash *flash = NULL;
-	int ret, i, shift;
-	u8 idcode[IDCODE_LEN], *idp;
-
-	spi = spi_setup_slave(bus, cs, max_hz, spi_mode);
-	if (!spi) {
-		printf("SF: Failed to set up slave\n");
-		return NULL;
-	}
-
-	ret = spi_claim_bus(spi);
-	if (ret) {
-		debug("SF: Failed to claim SPI bus: %d\n", ret);
-		goto err_claim_bus;
-	}
-
-	/* Read the ID codes */
-	ret = spi_flash_cmd(spi, CMD_READ_ID, idcode, sizeof(idcode));
-	if (ret)
-		goto err_read_id;
-
-#ifdef DEBUG
-	printf("SF: Got idcodes\n");
-	print_buffer(0, idcode, 1, sizeof(idcode), 0);
-#endif
-
-	/* count the number of continuation bytes */
-	for (shift = 0, idp = idcode;
-	     shift < IDCODE_CONT_LEN && *idp == 0x7f;
-	     ++shift, ++idp)
-		continue;
-
-	/* search the table for matches in shift and id */
-	for (i = 0; i < ARRAY_SIZE(flashes); ++i)
-		if (flashes[i].shift == shift && flashes[i].idcode == *idp) {
-			/* we have a match, call probe */
-			flash = flashes[i].probe(spi, idp);
-			if (flash)
-				break;
-		}
-
-	if (!flash) {
-		printf("SF: Unsupported manufacturer %02x\n", *idp);
-		goto err_manufacturer_probe;
-	}
-
-#ifdef CONFIG_SPI_FLASH_BAR
-	/* Configure the BAR - disover bank cmds and read current bank  */
-	ret = spi_flash_bank_config(flash, *idp);
-	if (ret < 0)
-		goto err_manufacturer_probe;
-#endif
-
-#ifdef CONFIG_OF_CONTROL
-	if (spi_flash_decode_fdt(gd->fdt_blob, flash)) {
-		debug("SF: FDT decode error\n");
-		goto err_manufacturer_probe;
-	}
-#endif
-#ifndef CONFIG_SPL_BUILD
-	printf("SF: Detected %s with page size ", flash->name);
-	print_size(flash->sector_size, ", total ");
-	print_size(flash->size, "");
-	if (flash->memory_map)
-		printf(", mapped at %p", flash->memory_map);
-	puts("\n");
-#endif
-#ifndef CONFIG_SPI_FLASH_BAR
-	if (flash->size > SPI_FLASH_16MB_BOUN) {
-		puts("SF: Warning - Only lower 16MiB accessible,");
-		puts(" Full access #define CONFIG_SPI_FLASH_BAR\n");
-	}
-#endif
-
-	spi_release_bus(spi);
-
-	return flash;
-
-err_manufacturer_probe:
-err_read_id:
-	spi_release_bus(spi);
-err_claim_bus:
-	spi_free_slave(spi);
-	return NULL;
-}
-
-void *spi_flash_do_alloc(int offset, int size, struct spi_slave *spi,
-			 const char *name)
-{
-	struct spi_flash *flash;
-	void *ptr;
-
-	ptr = malloc(size);
-	if (!ptr) {
-		debug("SF: Failed to allocate memory\n");
-		return NULL;
-	}
-	memset(ptr, '\0', size);
-	flash = (struct spi_flash *)(ptr + offset);
-
-	/* Set up some basic fields - caller will sort out sizes */
-	flash->spi = spi;
-	flash->name = name;
-	flash->poll_cmd = CMD_READ_STATUS;
-
-	flash->read = spi_flash_cmd_read_fast;
-	flash->write = spi_flash_cmd_write_multi;
-	flash->erase = spi_flash_cmd_erase;
-
-	return flash;
-}
-
-void spi_flash_free(struct spi_flash *flash)
-{
-	spi_free_slave(flash->spi);
-	free(flash);
-}
diff --git a/drivers/mtd/spi/sst.c b/drivers/mtd/spi/sst.c
deleted file mode 100644
index 256867c..0000000
--- a/drivers/mtd/spi/sst.c
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * Driver for SST serial flashes
- *
- * (C) Copyright 2000-2002
- * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
- * Copyright 2008, Network Appliance Inc.
- * Jason McMullan <mcmullan@netapp.com>
- * Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
- * TsiChung Liew (Tsi-Chung.Liew@freescale.com)
- * Copyright (c) 2008-2009 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-
-#include <common.h>
-#include <malloc.h>
-#include <spi_flash.h>
-
-#include "spi_flash_internal.h"
-
-#define CMD_SST_BP		0x02	/* Byte Program */
-#define CMD_SST_AAI_WP		0xAD	/* Auto Address Incr Word Program */
-
-#define SST_SR_WIP		(1 << 0)	/* Write-in-Progress */
-#define SST_SR_WEL		(1 << 1)	/* Write enable */
-#define SST_SR_BP0		(1 << 2)	/* Block Protection 0 */
-#define SST_SR_BP1		(1 << 3)	/* Block Protection 1 */
-#define SST_SR_BP2		(1 << 4)	/* Block Protection 2 */
-#define SST_SR_AAI		(1 << 6)	/* Addressing mode */
-#define SST_SR_BPL		(1 << 7)	/* BP bits lock */
-
-#define SST_FEAT_WP		(1 << 0)	/* Supports AAI word program */
-#define SST_FEAT_MBP		(1 << 1)	/* Supports multibyte program */
-
-struct sst_spi_flash_params {
-	u8 idcode1;
-	u8 flags;
-	u16 nr_sectors;
-	const char *name;
-};
-
-struct sst_spi_flash {
-	struct spi_flash flash;
-	const struct sst_spi_flash_params *params;
-};
-
-static const struct sst_spi_flash_params sst_spi_flash_table[] = {
-	{
-		.idcode1 = 0x8d,
-		.flags = SST_FEAT_WP,
-		.nr_sectors = 128,
-		.name = "SST25VF040B",
-	},
-	{
-		.idcode1 = 0x8e,
-		.flags = SST_FEAT_WP,
-		.nr_sectors = 256,
-		.name = "SST25VF080B",
-	},
-	{
-		.idcode1 = 0x41,
-		.flags = SST_FEAT_WP,
-		.nr_sectors = 512,
-		.name = "SST25VF016B",
-	},
-	{
-		.idcode1 = 0x4a,
-		.flags = SST_FEAT_WP,
-		.nr_sectors = 1024,
-		.name = "SST25VF032B",
-	},
-	{
-		.idcode1 = 0x4b,
-		.flags = SST_FEAT_MBP,
-		.nr_sectors = 2048,
-		.name = "SST25VF064C",
-	},
-	{
-		.idcode1 = 0x01,
-		.flags = SST_FEAT_WP,
-		.nr_sectors = 16,
-		.name = "SST25WF512",
-	},
-	{
-		.idcode1 = 0x02,
-		.flags = SST_FEAT_WP,
-		.nr_sectors = 32,
-		.name = "SST25WF010",
-	},
-	{
-		.idcode1 = 0x03,
-		.flags = SST_FEAT_WP,
-		.nr_sectors = 64,
-		.name = "SST25WF020",
-	},
-	{
-		.idcode1 = 0x04,
-		.flags = SST_FEAT_WP,
-		.nr_sectors = 128,
-		.name = "SST25WF040",
-	},
-	{
-		.idcode1 = 0x05,
-		.flags = SST_FEAT_WP,
-		.nr_sectors = 256,
-		.name = "SST25WF080",
-	},
-};
-
-static int
-sst_byte_write(struct spi_flash *flash, u32 offset, const void *buf)
-{
-	int ret;
-	u8 cmd[4] = {
-		CMD_SST_BP,
-		offset >> 16,
-		offset >> 8,
-		offset,
-	};
-
-	debug("BP[%02x]: 0x%p => cmd = { 0x%02x 0x%06x }\n",
-	      spi_w8r8(flash->spi, CMD_READ_STATUS), buf, cmd[0], offset);
-
-	ret = spi_flash_cmd_write_enable(flash);
-	if (ret)
-		return ret;
-
-	ret = spi_flash_cmd_write(flash->spi, cmd, sizeof(cmd), buf, 1);
-	if (ret)
-		return ret;
-
-	return spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
-}
-
-static int
-sst_write_wp(struct spi_flash *flash, u32 offset, size_t len, const void *buf)
-{
-	size_t actual, cmd_len;
-	int ret;
-	u8 cmd[4];
-
-	ret = spi_claim_bus(flash->spi);
-	if (ret) {
-		debug("SF: Unable to claim SPI bus\n");
-		return ret;
-	}
-
-	/* If the data is not word aligned, write out leading single byte */
-	actual = offset % 2;
-	if (actual) {
-		ret = sst_byte_write(flash, offset, buf);
-		if (ret)
-			goto done;
-	}
-	offset += actual;
-
-	ret = spi_flash_cmd_write_enable(flash);
-	if (ret)
-		goto done;
-
-	cmd_len = 4;
-	cmd[0] = CMD_SST_AAI_WP;
-	cmd[1] = offset >> 16;
-	cmd[2] = offset >> 8;
-	cmd[3] = offset;
-
-	for (; actual < len - 1; actual += 2) {
-		debug("WP[%02x]: 0x%p => cmd = { 0x%02x 0x%06x }\n",
-		      spi_w8r8(flash->spi, CMD_READ_STATUS), buf + actual,
-		      cmd[0], offset);
-
-		ret = spi_flash_cmd_write(flash->spi, cmd, cmd_len,
-					buf + actual, 2);
-		if (ret) {
-			debug("SF: sst word program failed\n");
-			break;
-		}
-
-		ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
-		if (ret)
-			break;
-
-		cmd_len = 1;
-		offset += 2;
-	}
-
-	if (!ret)
-		ret = spi_flash_cmd_write_disable(flash);
-
-	/* If there is a single trailing byte, write it out */
-	if (!ret && actual != len)
-		ret = sst_byte_write(flash, offset, buf + actual);
-
- done:
-	debug("SF: sst: program %s %zu bytes @ 0x%zx\n",
-	      ret ? "failure" : "success", len, offset - actual);
-
-	spi_release_bus(flash->spi);
-	return ret;
-}
-
-struct spi_flash *
-spi_flash_probe_sst(struct spi_slave *spi, u8 *idcode)
-{
-	const struct sst_spi_flash_params *params;
-	struct sst_spi_flash *stm;
-	size_t i;
-
-	for (i = 0; i < ARRAY_SIZE(sst_spi_flash_table); ++i) {
-		params = &sst_spi_flash_table[i];
-		if (params->idcode1 == idcode[2])
-			break;
-	}
-
-	if (i == ARRAY_SIZE(sst_spi_flash_table)) {
-		debug("SF: Unsupported SST ID %02x\n", idcode[1]);
-		return NULL;
-	}
-
-	stm = spi_flash_alloc(struct sst_spi_flash, spi, params->name);
-	if (!stm) {
-		debug("SF: Failed to allocate memory\n");
-		return NULL;
-	}
-
-	stm->params = params;
-
-	if (stm->params->flags & SST_FEAT_WP)
-		stm->flash.write = sst_write_wp;
-	stm->flash.page_size = 256;
-	stm->flash.sector_size = 4096;
-	stm->flash.size = stm->flash.sector_size * params->nr_sectors;
-
-	/* Flash powers up read-only, so clear BP# bits */
-	spi_flash_cmd_write_status(&stm->flash, 0);
-
-	return &stm->flash;
-}
diff --git a/drivers/mtd/spi/stmicro.c b/drivers/mtd/spi/stmicro.c
deleted file mode 100644
index c5fa64e..0000000
--- a/drivers/mtd/spi/stmicro.c
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * (C) Copyright 2000-2002
- * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
- *
- * Copyright 2008, Network Appliance Inc.
- * Jason McMullan <mcmullan@netapp.com>
- *
- * Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
- * TsiChung Liew (Tsi-Chung.Liew@freescale.com)
- *
- * SPDX-License-Identifier:	GPL-2.0+
- */
-
-#include <common.h>
-#include <malloc.h>
-#include <spi_flash.h>
-
-#include "spi_flash_internal.h"
-
-/* M25Pxx-specific commands */
-#define CMD_M25PXX_RES	0xab	/* Release from DP, and Read Signature */
-
-struct stmicro_spi_flash_params {
-	u16 id;
-	u16 pages_per_sector;
-	u16 nr_sectors;
-	const char *name;
-};
-
-static const struct stmicro_spi_flash_params stmicro_spi_flash_table[] = {
-	{
-		.id = 0x2011,
-		.pages_per_sector = 128,
-		.nr_sectors = 4,
-		.name = "M25P10",
-	},
-	{
-		.id = 0x2015,
-		.pages_per_sector = 256,
-		.nr_sectors = 32,
-		.name = "M25P16",
-	},
-	{
-		.id = 0x2012,
-		.pages_per_sector = 256,
-		.nr_sectors = 4,
-		.name = "M25P20",
-	},
-	{
-		.id = 0x2016,
-		.pages_per_sector = 256,
-		.nr_sectors = 64,
-		.name = "M25P32",
-	},
-	{
-		.id = 0x2013,
-		.pages_per_sector = 256,
-		.nr_sectors = 8,
-		.name = "M25P40",
-	},
-	{
-		.id = 0x2017,
-		.pages_per_sector = 256,
-		.nr_sectors = 128,
-		.name = "M25P64",
-	},
-	{
-		.id = 0x2014,
-		.pages_per_sector = 256,
-		.nr_sectors = 16,
-		.name = "M25P80",
-	},
-	{
-		.id = 0x2018,
-		.pages_per_sector = 1024,
-		.nr_sectors = 64,
-		.name = "M25P128",
-	},
-	{
-		.id = 0xba16,
-		.pages_per_sector = 256,
-		.nr_sectors = 64,
-		.name = "N25Q32",
-	},
-	{
-		.id = 0xbb16,
-		.pages_per_sector = 256,
-		.nr_sectors = 64,
-		.name = "N25Q32A",
-	},
-	{
-		.id = 0xba17,
-		.pages_per_sector = 256,
-		.nr_sectors = 128,
-		.name = "N25Q064",
-	},
-	{
-		.id = 0xbb17,
-		.pages_per_sector = 256,
-		.nr_sectors = 128,
-		.name = "N25Q64A",
-	},
-	{
-		.id = 0xba18,
-		.pages_per_sector = 256,
-		.nr_sectors = 256,
-		.name = "N25Q128",
-	},
-	{
-		.id = 0xbb18,
-		.pages_per_sector = 256,
-		.nr_sectors = 256,
-		.name = "N25Q128A",
-	},
-	{
-		.id = 0xba19,
-		.pages_per_sector = 256,
-		.nr_sectors = 512,
-		.name = "N25Q256",
-	},
-	{
-		.id = 0xbb19,
-		.pages_per_sector = 256,
-		.nr_sectors = 512,
-		.name = "N25Q256A",
-	},
-	{
-		.id = 0xba20,
-		.pages_per_sector = 256,
-		.nr_sectors = 1024,
-		.name = "N25Q512",
-	},
-	{
-		.id = 0xbb20,
-		.pages_per_sector = 256,
-		.nr_sectors = 1024,
-		.name = "N25Q512A",
-	},
-	{
-		.id = 0xba21,
-		.pages_per_sector = 256,
-		.nr_sectors = 2048,
-		.name = "N25Q1024",
-	},
-	{
-		.id = 0xbb21,
-		.pages_per_sector = 256,
-		.nr_sectors = 2048,
-		.name = "N25Q1024A",
-	},
-};
-
-struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 *idcode)
-{
-	const struct stmicro_spi_flash_params *params;
-	struct spi_flash *flash;
-	unsigned int i;
-	u16 id;
-
-	if (idcode[0] == 0xff) {
-		i = spi_flash_cmd(spi, CMD_M25PXX_RES,
-				  idcode, 4);
-		if (i)
-			return NULL;
-		if ((idcode[3] & 0xf0) == 0x10) {
-			idcode[0] = 0x20;
-			idcode[1] = 0x20;
-			idcode[2] = idcode[3] + 1;
-		} else {
-			return NULL;
-		}
-	}
-
-	id = ((idcode[1] << 8) | idcode[2]);
-
-	for (i = 0; i < ARRAY_SIZE(stmicro_spi_flash_table); i++) {
-		params = &stmicro_spi_flash_table[i];
-		if (params->id == id)
-			break;
-	}
-
-	if (i == ARRAY_SIZE(stmicro_spi_flash_table)) {
-		debug("SF: Unsupported STMicro ID %04x\n", id);
-		return NULL;
-	}
-
-	flash = spi_flash_alloc_base(spi, params->name);
-	if (!flash) {
-		debug("SF: Failed to allocate memory\n");
-		return NULL;
-	}
-
-	flash->page_size = 256;
-	flash->sector_size = 256 * params->pages_per_sector;
-	flash->size = flash->sector_size * params->nr_sectors;
-
-	/* for >= 512MiB flashes, use flag status instead of read_status */
-	if (flash->size >= 0x4000000)
-		flash->poll_cmd = CMD_FLAG_STATUS;
-
-	return flash;
-}
diff --git a/drivers/mtd/spi/winbond.c b/drivers/mtd/spi/winbond.c
deleted file mode 100644
index b31911a..0000000
--- a/drivers/mtd/spi/winbond.c
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright 2008, Network Appliance Inc.
- * Author: Jason McMullan <mcmullan <at> netapp.com>
- * Licensed under the GPL-2 or later.
- */
-
-#include <common.h>
-#include <malloc.h>
-#include <spi_flash.h>
-
-#include "spi_flash_internal.h"
-
-struct winbond_spi_flash_params {
-	uint16_t	id;
-	uint16_t	nr_blocks;
-	const char	*name;
-};
-
-static const struct winbond_spi_flash_params winbond_spi_flash_table[] = {
-	{
-		.id			= 0x2014,
-		.nr_blocks		= 16,
-		.name			= "W25P80",
-	},
-	{
-		.id			= 0x2015,
-		.nr_blocks		= 32,
-		.name			= "W25P16",
-	},
-	{
-		.id			= 0x2016,
-		.nr_blocks		= 64,
-		.name			= "W25P32",
-	},
-	{
-		.id			= 0x3013,
-		.nr_blocks		= 8,
-		.name			= "W25X40",
-	},
-	{
-		.id			= 0x3015,
-		.nr_blocks		= 32,
-		.name			= "W25X16",
-	},
-	{
-		.id			= 0x3016,
-		.nr_blocks		= 64,
-		.name			= "W25X32",
-	},
-	{
-		.id			= 0x3017,
-		.nr_blocks		= 128,
-		.name			= "W25X64",
-	},
-	{
-		.id			= 0x4014,
-		.nr_blocks		= 16,
-		.name			= "W25Q80BL/W25Q80BV",
-	},
-	{
-		.id			= 0x4015,
-		.nr_blocks		= 32,
-		.name			= "W25Q16CL/W25Q16DV",
-	},
-	{
-		.id			= 0x4016,
-		.nr_blocks		= 64,
-		.name			= "W25Q32BV/W25Q32FV_SPI",
-	},
-	{
-		.id			= 0x4017,
-		.nr_blocks		= 128,
-		.name			= "W25Q64CV/W25Q64FV_SPI",
-	},
-	{
-		.id			= 0x4018,
-		.nr_blocks		= 256,
-		.name			= "W25Q128BV/W25Q128FV_SPI",
-	},
-	{
-		.id			= 0x4019,
-		.nr_blocks		= 512,
-		.name			= "W25Q256",
-	},
-	{
-		.id			= 0x5014,
-		.nr_blocks		= 16,
-		.name			= "W25Q80BW",
-	},
-	{
-		.id			= 0x6015,
-		.nr_blocks		= 32,
-		.name			= "W25Q16DW",
-	},
-	{
-		.id			= 0x6016,
-		.nr_blocks		= 64,
-		.name			= "W25Q32DW/W25Q32FV_QPI",
-	},
-	{
-		.id			= 0x6017,
-		.nr_blocks		= 128,
-		.name			= "W25Q64DW/W25Q64FV_QPI",
-	},
-	{
-		.id			= 0x6018,
-		.nr_blocks		= 256,
-		.name			= "W25Q128FW/W25Q128FV_QPI",
-	},
-};
-
-struct spi_flash *spi_flash_probe_winbond(struct spi_slave *spi, u8 *idcode)
-{
-	const struct winbond_spi_flash_params *params;
-	struct spi_flash *flash;
-	unsigned int i;
-
-	for (i = 0; i < ARRAY_SIZE(winbond_spi_flash_table); i++) {
-		params = &winbond_spi_flash_table[i];
-		if (params->id == ((idcode[1] << 8) | idcode[2]))
-			break;
-	}
-
-	if (i == ARRAY_SIZE(winbond_spi_flash_table)) {
-		debug("SF: Unsupported Winbond ID %02x%02x\n",
-		      idcode[1], idcode[2]);
-		return NULL;
-	}
-
-	flash = spi_flash_alloc_base(spi, params->name);
-	if (!flash) {
-		debug("SF: Failed to allocate memory\n");
-		return NULL;
-	}
-
-	flash->page_size = 256;
-	flash->sector_size = (idcode[1] == 0x20) ? 65536 : 4096;
-	flash->size = 4096 * 16 * params->nr_blocks;
-
-	return flash;
-}
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 91d24ce..e5941b0 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -38,6 +38,7 @@
 COBJS-$(CONFIG_TEGRA20_SFLASH) += tegra20_sflash.o
 COBJS-$(CONFIG_TEGRA20_SLINK) += tegra20_slink.o
 COBJS-$(CONFIG_TEGRA114_SPI) += tegra114_spi.o
+COBJS-$(CONFIG_TI_QSPI) += ti_qspi.o
 COBJS-$(CONFIG_XILINX_SPI) += xilinx_spi.o
 COBJS-$(CONFIG_ZYNQ_SPI) += zynq_spi.o
 
diff --git a/drivers/spi/exynos_spi.c b/drivers/spi/exynos_spi.c
index efc8b1e..699c57e 100644
--- a/drivers/spi/exynos_spi.c
+++ b/drivers/spi/exynos_spi.c
@@ -26,6 +26,7 @@
 	struct exynos_spi *regs;
 	int inited;		/* 1 if this bus is ready for use */
 	int node;
+	uint deactivate_delay_us;	/* Delay to wait after deactivate */
 };
 
 /* A list of spi buses that we know about */
@@ -40,6 +41,8 @@
 	enum periph_id periph_id;	/* Peripheral ID for this device */
 	unsigned int fifo_size;
 	int skip_preamble;
+	struct spi_bus *bus;		/* Pointer to our SPI bus info */
+	ulong last_transaction_us;	/* Time of last transaction end */
 };
 
 static struct spi_bus *spi_get_bus(unsigned dev_index)
@@ -85,6 +88,7 @@
 	}
 
 	bus = &spi_bus[busnum];
+	spi_slave->bus = bus;
 	spi_slave->regs = bus->regs;
 	spi_slave->mode = mode;
 	spi_slave->periph_id = bus->periph_id;
@@ -95,6 +99,7 @@
 		spi_slave->fifo_size = 256;
 
 	spi_slave->skip_preamble = 0;
+	spi_slave->last_transaction_us = timer_get_us();
 
 	spi_slave->freq = bus->frequency;
 	if (max_hz)
@@ -199,12 +204,29 @@
  *
  * @param regs	SPI peripheral registers
  * @param count	Number of bytes to transfer
+ * @param step	Number of bytes to transfer in each packet (1 or 4)
  */
-static void spi_request_bytes(struct exynos_spi *regs, int count)
+static void spi_request_bytes(struct exynos_spi *regs, int count, int step)
 {
+	/* For word address we need to swap bytes */
+	if (step == 4) {
+		setbits_le32(&regs->mode_cfg,
+			     SPI_MODE_CH_WIDTH_WORD | SPI_MODE_BUS_WIDTH_WORD);
+		count /= 4;
+		setbits_le32(&regs->swap_cfg, SPI_TX_SWAP_EN | SPI_RX_SWAP_EN |
+			SPI_TX_BYTE_SWAP | SPI_RX_BYTE_SWAP |
+			SPI_TX_HWORD_SWAP | SPI_RX_HWORD_SWAP);
+	} else {
+		/* Select byte access and clear the swap configuration */
+		clrbits_le32(&regs->mode_cfg,
+			     SPI_MODE_CH_WIDTH_WORD | SPI_MODE_BUS_WIDTH_WORD);
+		writel(0, &regs->swap_cfg);
+	}
+
 	assert(count && count < (1 << 16));
 	setbits_le32(&regs->ch_cfg, SPI_CH_RST);
 	clrbits_le32(&regs->ch_cfg, SPI_CH_RST);
+
 	writel(count | SPI_PACKET_CNT_EN, &regs->pkt_cnt);
 }
 
@@ -219,6 +241,7 @@
 	int toread;
 	unsigned start = get_timer(0);
 	int stopping;
+	int step;
 
 	out_bytes = in_bytes = todo;
 
@@ -226,10 +249,19 @@
 					!(spi_slave->mode & SPI_SLAVE);
 
 	/*
+	 * Try to transfer words if we can. This helps read performance at
+	 * SPI clock speeds above about 20MHz.
+	 */
+	step = 1;
+	if (!((todo | (uintptr_t)rxp | (uintptr_t)txp) & 3) &&
+	    !spi_slave->skip_preamble)
+		step = 4;
+
+	/*
 	 * If there's something to send, do a software reset and set a
 	 * transaction size.
 	 */
-	spi_request_bytes(regs, todo);
+	spi_request_bytes(regs, todo, step);
 
 	/*
 	 * Bytes are transmitted/received in pairs. Wait to receive all the
@@ -242,24 +274,42 @@
 
 		/* Keep the fifos full/empty. */
 		spi_get_fifo_levels(regs, &rx_lvl, &tx_lvl);
-		if (tx_lvl < spi_slave->fifo_size && out_bytes) {
-			temp = txp ? *txp++ : 0xff;
+
+		/*
+		 * Don't completely fill the txfifo, since we don't want our
+		 * rxfifo to overflow, and it may already contain data.
+		 */
+		while (tx_lvl < spi_slave->fifo_size/2 && out_bytes) {
+			if (!txp)
+				temp = -1;
+			else if (step == 4)
+				temp = *(uint32_t *)txp;
+			else
+				temp = *txp;
 			writel(temp, &regs->tx_data);
-			out_bytes--;
+			out_bytes -= step;
+			if (txp)
+				txp += step;
+			tx_lvl += step;
 		}
-		if (rx_lvl > 0) {
-			temp = readl(&regs->rx_data);
-			if (spi_slave->skip_preamble) {
-				if (temp == SPI_PREAMBLE_END_BYTE) {
-					spi_slave->skip_preamble = 0;
-					stopping = 0;
+		if (rx_lvl >= step) {
+			while (rx_lvl >= step) {
+				temp = readl(&regs->rx_data);
+				if (spi_slave->skip_preamble) {
+					if (temp == SPI_PREAMBLE_END_BYTE) {
+						spi_slave->skip_preamble = 0;
+						stopping = 0;
+					}
+				} else {
+					if (rxp || stopping) {
+						*rxp = temp;
+						rxp += step;
+					}
+					in_bytes -= step;
 				}
-			} else {
-				if (rxp || stopping)
-					*rxp++ = temp;
-				in_bytes--;
+				toread -= step;
+				rx_lvl -= step;
 			}
-			toread--;
 		} else if (!toread) {
 			/*
 			 * We have run out of input data, but haven't read
@@ -271,7 +321,7 @@
 			out_bytes = in_bytes;
 			toread = in_bytes;
 			txp = NULL;
-			spi_request_bytes(regs, toread);
+			spi_request_bytes(regs, toread, step);
 		}
 		if (spi_slave->skip_preamble && get_timer(start) > 100) {
 			printf("SPI timeout: in_bytes=%d, out_bytes=%d, ",
@@ -315,10 +365,14 @@
 	if ((flags & SPI_XFER_BEGIN))
 		spi_cs_activate(slave);
 
-	/* Exynos SPI limits each transfer to 65535 bytes */
+	/*
+	 * Exynos SPI limits each transfer to 65535 transfers. To keep
+	 * things simple, allow a maximum of 65532 bytes. We could allow
+	 * more in word mode, but the performance difference is small.
+	 */
 	bytelen =  bitlen / 8;
 	for (upto = 0; !ret && upto < bytelen; upto += todo) {
-		todo = min(bytelen - upto, (1 << 16) - 1);
+		todo = min(bytelen - upto, (1 << 16) - 4);
 		ret = spi_rx_tx(spi_slave, todo, &din, &dout, flags);
 		if (ret)
 			break;
@@ -359,9 +413,22 @@
 {
 	struct exynos_spi_slave *spi_slave = to_exynos_spi(slave);
 
+	/* If it's too soon to do another transaction, wait */
+	if (spi_slave->bus->deactivate_delay_us &&
+	    spi_slave->last_transaction_us) {
+		ulong delay_us;		/* The delay completed so far */
+		delay_us = timer_get_us() - spi_slave->last_transaction_us;
+		if (delay_us < spi_slave->bus->deactivate_delay_us)
+			udelay(spi_slave->bus->deactivate_delay_us - delay_us);
+	}
+
 	clrbits_le32(&spi_slave->regs->cs_reg, SPI_SLAVE_SIG_INACT);
 	debug("Activate CS, bus %d\n", spi_slave->slave.bus);
 	spi_slave->skip_preamble = spi_slave->mode & SPI_PREAMBLE;
+
+	/* Remember time of this transaction so we can honour the bus delay */
+	if (spi_slave->bus->deactivate_delay_us)
+		spi_slave->last_transaction_us = timer_get_us();
 }
 
 /**
@@ -411,6 +478,8 @@
 	/* Use 500KHz as a suitable default */
 	bus->frequency = fdtdec_get_int(blob, node, "spi-max-frequency",
 					500000);
+	bus->deactivate_delay_us = fdtdec_get_int(blob, node,
+					"spi-deactivate-delay", 0);
 
 	return 0;
 }
diff --git a/drivers/spi/ti_qspi.c b/drivers/spi/ti_qspi.c
new file mode 100644
index 0000000..5a5b482
--- /dev/null
+++ b/drivers/spi/ti_qspi.c
@@ -0,0 +1,311 @@
+/*
+ * TI QSPI driver
+ *
+ * Copyright (C) 2013, Texas Instruments, Incorporated
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/omap.h>
+#include <malloc.h>
+#include <spi.h>
+
+/* ti qpsi register bit masks */
+#define QSPI_TIMEOUT                    2000000
+#define QSPI_FCLK                       192000000
+/* clock control */
+#define QSPI_CLK_EN                     (1 << 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_WR_SNGL                    (2 << 16)
+#define QSPI_INVAL                      (4 << 16)
+#define QSPI_RD_QUAD                    (7 << 16)
+/* device control */
+#define QSPI_DD(m, n)                   (m << (3 + n*8))
+#define QSPI_CKPHA(n)                   (1 << (2 + n*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_BUSY                    (QSPI_WC | QSPI_BUSY)
+#define QSPI_XFER_DONE                  QSPI_WC
+#define MM_SWITCH                       0x01
+#define MEM_CS                          0x100
+#define MEM_CS_UNSELECT                 0xfffff0ff
+#define MMAP_START_ADDR                 0x5c000000
+#define CORE_CTRL_IO                    0x4a002558
+
+#define QSPI_CMD_READ                   (0x3 << 0)
+#define QSPI_CMD_READ_QUAD              (0x6b << 0)
+#define QSPI_CMD_READ_FAST              (0x0b << 0)
+#define QSPI_SETUP0_NUM_A_BYTES         (0x2 << 8)
+#define QSPI_SETUP0_NUM_D_BYTES_NO_BITS (0x0 << 10)
+#define QSPI_SETUP0_NUM_D_BYTES_8_BITS  (0x1 << 10)
+#define QSPI_SETUP0_READ_NORMAL         (0x0 << 12)
+#define QSPI_SETUP0_READ_QUAD           (0x3 << 12)
+#define QSPI_CMD_WRITE                  (0x2 << 16)
+#define QSPI_NUM_DUMMY_BITS             (0x0 << 24)
+
+/* ti qspi register set */
+struct ti_qspi_regs {
+	u32 pid;
+	u32 pad0[3];
+	u32 sysconfig;
+	u32 pad1[3];
+	u32 int_stat_raw;
+	u32 int_stat_en;
+	u32 int_en_set;
+	u32 int_en_ctlr;
+	u32 intc_eoi;
+	u32 pad2[3];
+	u32 clk_ctrl;
+	u32 dc;
+	u32 cmd;
+	u32 status;
+	u32 data;
+	u32 setup0;
+	u32 setup1;
+	u32 setup2;
+	u32 setup3;
+	u32 memswitch;
+	u32 data1;
+	u32 data2;
+	u32 data3;
+};
+
+/* ti qspi slave */
+struct ti_qspi_slave {
+	struct spi_slave slave;
+	struct ti_qspi_regs *base;
+	unsigned int mode;
+	u32 cmd;
+	u32 dc;
+};
+
+static inline struct ti_qspi_slave *to_ti_qspi_slave(struct spi_slave *slave)
+{
+	return container_of(slave, struct ti_qspi_slave, slave);
+}
+
+static void ti_spi_setup_spi_register(struct ti_qspi_slave *qslave)
+{
+	struct spi_slave *slave = &qslave->slave;
+	u32 memval = 0;
+
+	slave->memory_map = (void *)MMAP_START_ADDR;
+
+	memval |= QSPI_CMD_READ | QSPI_SETUP0_NUM_A_BYTES |
+			QSPI_SETUP0_NUM_D_BYTES_NO_BITS |
+			QSPI_SETUP0_READ_NORMAL | QSPI_CMD_WRITE |
+			QSPI_NUM_DUMMY_BITS;
+
+	writel(memval, &qslave->base->setup0);
+}
+
+static void ti_spi_set_speed(struct spi_slave *slave, uint hz)
+{
+	struct ti_qspi_slave *qslave = to_ti_qspi_slave(slave);
+	uint clk_div;
+
+	debug("ti_spi_set_speed: hz: %d, clock divider %d\n", hz, clk_div);
+
+	if (!hz)
+		clk_div = 0;
+	else
+		clk_div = (QSPI_FCLK / hz) - 1;
+
+	/* disable SCLK */
+	writel(readl(&qslave->base->clk_ctrl) & ~QSPI_CLK_EN,
+	       &qslave->base->clk_ctrl);
+
+	/* assign clk_div values */
+	if (clk_div < 0)
+		clk_div = 0;
+	else if (clk_div > QSPI_CLK_DIV_MAX)
+		clk_div = QSPI_CLK_DIV_MAX;
+
+	/* enable SCLK */
+	writel(QSPI_CLK_EN | clk_div, &qslave->base->clk_ctrl);
+}
+
+int spi_cs_is_valid(unsigned int bus, unsigned int cs)
+{
+	return 1;
+}
+
+void spi_cs_activate(struct spi_slave *slave)
+{
+	/* CS handled in xfer */
+	return;
+}
+
+void spi_cs_deactivate(struct spi_slave *slave)
+{
+	struct ti_qspi_slave *qslave = to_ti_qspi_slave(slave);
+
+	debug("spi_cs_deactivate: 0x%08x\n", (u32)slave);
+
+	writel(qslave->cmd | QSPI_INVAL, &qslave->base->cmd);
+}
+
+void spi_init(void)
+{
+	/* nothing to do */
+}
+
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+				  unsigned int max_hz, unsigned int mode)
+{
+	struct ti_qspi_slave *qslave;
+
+	qslave = spi_alloc_slave(struct ti_qspi_slave, bus, cs);
+	if (!qslave) {
+		printf("SPI_error: Fail to allocate ti_qspi_slave\n");
+		return NULL;
+	}
+
+	qslave->base = (struct ti_qspi_regs *)QSPI_BASE;
+	qslave->mode = mode;
+
+	ti_spi_set_speed(&qslave->slave, max_hz);
+
+#ifdef CONFIG_TI_SPI_MMAP
+	ti_spi_setup_spi_register(qslave);
+#endif
+
+	return &qslave->slave;
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+	struct ti_qspi_slave *qslave = to_ti_qspi_slave(slave);
+	free(qslave);
+}
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+	struct ti_qspi_slave *qslave = to_ti_qspi_slave(slave);
+
+	debug("spi_claim_bus: bus:%i cs:%i\n", slave->bus, slave->cs);
+
+	qslave->dc = 0;
+	if (qslave->mode & SPI_CPHA)
+		qslave->dc |= QSPI_CKPHA(slave->cs);
+	if (qslave->mode & SPI_CPOL)
+		qslave->dc |= QSPI_CKPOL(slave->cs);
+	if (qslave->mode & SPI_CS_HIGH)
+		qslave->dc |= QSPI_CSPOL(slave->cs);
+
+	writel(qslave->dc, &qslave->base->dc);
+	writel(0, &qslave->base->cmd);
+	writel(0, &qslave->base->data);
+
+	return 0;
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+	struct ti_qspi_slave *qslave = to_ti_qspi_slave(slave);
+
+	debug("spi_release_bus: bus:%i cs:%i\n", slave->bus, slave->cs);
+
+	writel(0, &qslave->base->dc);
+	writel(0, &qslave->base->cmd);
+	writel(0, &qslave->base->data);
+}
+
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
+	     void *din, unsigned long flags)
+{
+	struct ti_qspi_slave *qslave = to_ti_qspi_slave(slave);
+	uint words = bitlen >> 3; /* fixed 8-bit word length */
+	const uchar *txp = dout;
+	uchar *rxp = din;
+	uint status;
+	int timeout, val;
+
+	debug("spi_xfer: bus:%i cs:%i bitlen:%i words:%i flags:%lx\n",
+	      slave->bus, slave->cs, bitlen, words, flags);
+
+	/* Setup mmap flags */
+	if (flags & SPI_XFER_MMAP) {
+		writel(MM_SWITCH, &qslave->base->memswitch);
+		val = readl(CORE_CTRL_IO);
+		val |= MEM_CS;
+		writel(val, CORE_CTRL_IO);
+		return 0;
+	} else if (flags & SPI_XFER_MMAP_END) {
+		writel(~MM_SWITCH, &qslave->base->memswitch);
+		val = readl(CORE_CTRL_IO);
+		val &= MEM_CS_UNSELECT;
+		writel(val, CORE_CTRL_IO);
+		return 0;
+	}
+
+	if (bitlen == 0)
+		return -1;
+
+	if (bitlen % 8) {
+		debug("spi_xfer: Non byte aligned SPI transfer\n");
+		return -1;
+	}
+
+	/* Setup command reg */
+	qslave->cmd = 0;
+	qslave->cmd |= QSPI_WLEN(8);
+	qslave->cmd |= QSPI_EN_CS(slave->cs);
+	if (flags & SPI_3WIRE)
+		qslave->cmd |= QSPI_3_PIN;
+	qslave->cmd |= 0xfff;
+
+	while (words--) {
+		if (txp) {
+			debug("tx cmd %08x dc %08x data %02x\n",
+			      qslave->cmd | QSPI_WR_SNGL, qslave->dc, *txp);
+			writel(*txp++, &qslave->base->data);
+			writel(qslave->cmd | QSPI_WR_SNGL,
+			       &qslave->base->cmd);
+			status = readl(&qslave->base->status);
+			timeout = QSPI_TIMEOUT;
+			while ((status & QSPI_WC_BUSY) != QSPI_XFER_DONE) {
+				if (--timeout < 0) {
+					printf("spi_xfer: TX timeout!\n");
+					return -1;
+				}
+				status = readl(&qslave->base->status);
+			}
+			debug("tx done, status %08x\n", status);
+		}
+		if (rxp) {
+			qslave->cmd |= QSPI_RD_SNGL;
+			debug("rx cmd %08x dc %08x\n",
+			      qslave->cmd, qslave->dc);
+			writel(qslave->cmd, &qslave->base->cmd);
+			status = readl(&qslave->base->status);
+			timeout = QSPI_TIMEOUT;
+			while ((status & QSPI_WC_BUSY) != QSPI_XFER_DONE) {
+				if (--timeout < 0) {
+					printf("spi_xfer: RX timeout!\n");
+					return -1;
+				}
+				status = readl(&qslave->base->status);
+			}
+			*rxp++ = readl(&qslave->base->data);
+			debug("rx done, status %08x, read %02x\n",
+			      status, *(rxp-1));
+		}
+	}
+
+	/* Terminate frame */
+	if (flags & SPI_XFER_END)
+		spi_cs_deactivate(slave);
+
+	return 0;
+}
diff --git a/include/common.h b/include/common.h
index f1a590a..bed4316 100644
--- a/include/common.h
+++ b/include/common.h
@@ -596,6 +596,12 @@
 #endif
 #endif
 
+/*
+ * Return the current value of a monotonically increasing microsecond timer.
+ * Granularity may be larger than 1us if hardware does not support this.
+ */
+ulong timer_get_us(void);
+
 /* $(CPU)/cpu.c */
 static inline int cpumask_next(int cpu, unsigned int mask)
 {
diff --git a/include/configs/dra7xx_evm.h b/include/configs/dra7xx_evm.h
index 7b120de..51e0e80 100644
--- a/include/configs/dra7xx_evm.h
+++ b/include/configs/dra7xx_evm.h
@@ -48,4 +48,23 @@
 #define CONFIG_PHYLIB
 #define CONFIG_PHY_ADDR			2
 
+/* SPI */
+#undef	CONFIG_OMAP3_SPI
+#define CONFIG_TI_QSPI
+#define CONFIG_SPI_FLASH
+#define CONFIG_SPI_FLASH_SPANSION
+#define CONFIG_CMD_SF
+#define CONFIG_CMD_SPI
+#define CONFIG_TI_SPI_MMAP
+#define CONFIG_SF_DEFAULT_SPEED                48000000
+#define CONFIG_DEFAULT_SPI_MODE                SPI_MODE_3
+
+/* SPI SPL */
+#define CONFIG_SPL_SPI_SUPPORT
+#define CONFIG_SPL_SPI_LOAD
+#define CONFIG_SPL_SPI_FLASH_SUPPORT
+#define CONFIG_SPL_SPI_BUS             0
+#define CONFIG_SPL_SPI_CS              0
+#define CONFIG_SYS_SPI_U_BOOT_OFFS     0x20000
+
 #endif /* __CONFIG_DRA7XX_EVM_H */
diff --git a/include/configs/top9000.h b/include/configs/top9000.h
index 65dabde..a6d6928 100644
--- a/include/configs/top9000.h
+++ b/include/configs/top9000.h
@@ -120,7 +120,6 @@
 #define CONFIG_ATMEL_SPI0		/* SPI used for FRAM is SPI0 */
 #define FRAM_SPI_BUS		0
 #define FRAM_CS_NUM		0
-#define CONFIG_SPI_FLASH		/* RAMTRON FRAM on SPI bus */
 #define CONFIG_SPI_FRAM_RAMTRON
 #define CONFIG_SF_DEFAULT_SPEED	1000000	/* be conservative here... */
 #define CONFIG_SF_DEFAULT_MODE	SPI_MODE_0
diff --git a/include/spi.h b/include/spi.h
index c0dab57..5164d43 100644
--- a/include/spi.h
+++ b/include/spi.h
@@ -25,29 +25,33 @@
 #define	SPI_PREAMBLE	0x80			/* Skip preamble bytes */
 
 /* SPI transfer flags */
-#define SPI_XFER_BEGIN	0x01			/* Assert CS before transfer */
-#define SPI_XFER_END	0x02			/* Deassert CS after transfer */
+#define SPI_XFER_BEGIN		0x01	/* Assert CS before transfer */
+#define SPI_XFER_END		0x02	/* Deassert CS after transfer */
+#define SPI_XFER_MMAP		0x08	/* Memory Mapped start */
+#define SPI_XFER_MMAP_END	0x10	/* Memory Mapped End */
 
 /* Header byte that marks the start of the message */
 #define SPI_PREAMBLE_END_BYTE	0xec
 
-/*-----------------------------------------------------------------------
- * Representation of a SPI slave, i.e. what we're communicating with.
+/**
+ * struct spi_slave - Representation of a SPI slave
  *
  * Drivers are expected to extend this with controller-specific data.
  *
- *   bus:	ID of the bus that the slave is attached to.
- *   cs:	ID of the chip select connected to the slave.
- *   max_write_size:	If non-zero, the maximum number of bytes which can
- *		be written at once, excluding command bytes.
+ * @bus:		ID of the bus that the slave is attached to.
+ * @cs:			ID of the chip select connected to the slave.
+ * @max_write_size:	If non-zero, the maximum number of bytes which can
+ *			be written at once, excluding command bytes.
+ * @memory_map:		Address of read-only SPI flash access.
  */
 struct spi_slave {
-	unsigned int	bus;
-	unsigned int	cs;
+	unsigned int bus;
+	unsigned int cs;
 	unsigned int max_write_size;
+	void *memory_map;
 };
 
-/*-----------------------------------------------------------------------
+/**
  * Initialization, must be called once on start up.
  *
  * TODO: I don't think we really need this.
@@ -60,10 +64,10 @@
  * Allocate and zero all fields in the spi slave, and set the bus/chip
  * select. Use the helper macro spi_alloc_slave() to call this.
  *
- * @offset: Offset of struct spi_slave within slave structure
- * @size: Size of slave structure
- * @bus: Bus ID of the slave chip.
- * @cs: Chip select ID of the slave chip on the specified bus.
+ * @offset:	Offset of struct spi_slave within slave structure.
+ * @size:	Size of slave structure.
+ * @bus:	Bus ID of the slave chip.
+ * @cs:		Chip select ID of the slave chip on the specified bus.
  */
 void *spi_do_alloc_slave(int offset, int size, unsigned int bus,
 			 unsigned int cs);
@@ -74,10 +78,10 @@
  * Allocate and zero all fields in the spi slave, and set the bus/chip
  * select.
  *
- * @_struct: Name of structure to allocate (e.g. struct tegra_spi). This
- *	structure must contain a member 'struct spi_slave *slave'.
- * @bus: Bus ID of the slave chip.
- * @cs: Chip select ID of the slave chip on the specified bus.
+ * @_struct:	Name of structure to allocate (e.g. struct tegra_spi).
+ *		This structure must contain a member 'struct spi_slave *slave'.
+ * @bus:	Bus ID of the slave chip.
+ * @cs:		Chip select ID of the slave chip on the specified bus.
  */
 #define spi_alloc_slave(_struct, bus, cs) \
 	spi_do_alloc_slave(offsetof(_struct, slave), \
@@ -89,13 +93,13 @@
  * Allocate and zero all fields in the spi slave, and set the bus/chip
  * select.
  *
- * @bus: Bus ID of the slave chip.
- * @cs: Chip select ID of the slave chip on the specified bus.
+ * @bus:	Bus ID of the slave chip.
+ * @cs:		Chip select ID of the slave chip on the specified bus.
  */
 #define spi_alloc_slave_base(bus, cs) \
 	spi_do_alloc_slave(0, sizeof(struct spi_slave), bus, cs)
 
-/*-----------------------------------------------------------------------
+/**
  * Set up communications parameters for a SPI slave.
  *
  * This must be called once for each slave. Note that this function
@@ -103,10 +107,10 @@
  * contents of spi_slave so that the hardware can be easily
  * initialized later.
  *
- *   bus:     Bus ID of the slave chip.
- *   cs:      Chip select ID of the slave chip on the specified bus.
- *   max_hz:  Maximum SCK rate in Hz.
- *   mode:    Clock polarity, clock phase and other parameters.
+ * @bus:	Bus ID of the slave chip.
+ * @cs:		Chip select ID of the slave chip on the specified bus.
+ * @max_hz:	Maximum SCK rate in Hz.
+ * @mode:	Clock polarity, clock phase and other parameters.
  *
  * Returns: A spi_slave reference that can be used in subsequent SPI
  * calls, or NULL if one or more of the parameters are not supported.
@@ -114,14 +118,14 @@
 struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
 		unsigned int max_hz, unsigned int mode);
 
-/*-----------------------------------------------------------------------
+/**
  * Free any memory associated with a SPI slave.
  *
- *   slave:	The SPI slave
+ * @slave:	The SPI slave
  */
 void spi_free_slave(struct spi_slave *slave);
 
-/*-----------------------------------------------------------------------
+/**
  * Claim the bus and prepare it for communication with a given slave.
  *
  * This must be called before doing any transfers with a SPI slave. It
@@ -130,25 +134,25 @@
  * allowed to claim the same bus for several slaves without releasing
  * the bus in between.
  *
- *   slave:	The SPI slave
+ * @slave:	The SPI slave
  *
  * Returns: 0 if the bus was claimed successfully, or a negative value
  * if it wasn't.
  */
 int spi_claim_bus(struct spi_slave *slave);
 
-/*-----------------------------------------------------------------------
+/**
  * Release the SPI bus
  *
  * This must be called once for every call to spi_claim_bus() after
  * all transfers have finished. It may disable any SPI hardware as
  * appropriate.
  *
- *   slave:	The SPI slave
+ * @slave:	The SPI slave
  */
 void spi_release_bus(struct spi_slave *slave);
 
-/*-----------------------------------------------------------------------
+/**
  * SPI transfer
  *
  * This writes "bitlen" bits out the SPI MOSI port and simultaneously clocks
@@ -161,19 +165,19 @@
  * temporary variables, this is OK).
  *
  * spi_xfer() interface:
- *   slave:	The SPI slave which will be sending/receiving the data.
- *   bitlen:	How many bits to write and read.
- *   dout:	Pointer to a string of bits to send out.  The bits are
+ * @slave:	The SPI slave which will be sending/receiving the data.
+ * @bitlen:	How many bits to write and read.
+ * @dout:	Pointer to a string of bits to send out.  The bits are
  *		held in a byte array and are sent MSB first.
- *   din:	Pointer to a string of bits that will be filled in.
- *   flags:	A bitwise combination of SPI_XFER_* flags.
+ * @din:	Pointer to a string of bits that will be filled in.
+ * @flags:	A bitwise combination of SPI_XFER_* flags.
  *
- *   Returns: 0 on success, not 0 on failure
+ * Returns: 0 on success, not 0 on failure
  */
 int  spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
 		void *din, unsigned long flags);
 
-/*-----------------------------------------------------------------------
+/**
  * Determine if a SPI chipselect is valid.
  * This function is provided by the board if the low-level SPI driver
  * needs it to determine if a given chipselect is actually valid.
@@ -183,7 +187,7 @@
  */
 int  spi_cs_is_valid(unsigned int bus, unsigned int cs);
 
-/*-----------------------------------------------------------------------
+/**
  * Activate a SPI chipselect.
  * This function is provided by the board code when using a driver
  * that can't control its chipselects automatically (e.g.
@@ -192,7 +196,7 @@
  */
 void spi_cs_activate(struct spi_slave *slave);
 
-/*-----------------------------------------------------------------------
+/**
  * Deactivate a SPI chipselect.
  * This function is provided by the board code when using a driver
  * that can't control its chipselects automatically (e.g.
@@ -201,18 +205,18 @@
  */
 void spi_cs_deactivate(struct spi_slave *slave);
 
-/*-----------------------------------------------------------------------
+/**
  * Set transfer speed.
  * This sets a new speed to be applied for next spi_xfer().
- *   slave:	The SPI slave
- *   hz:	The transfer speed
+ * @slave:	The SPI slave
+ * @hz:		The transfer speed
  */
 void spi_set_speed(struct spi_slave *slave, uint hz);
 
-/*-----------------------------------------------------------------------
+/**
  * Write 8 bits, then read 8 bits.
- *   slave:	The SPI slave we're communicating with
- *   byte:	Byte to be written
+ * @slave:	The SPI slave we're communicating with
+ * @byte:	Byte to be written
  *
  * Returns: The value that was read, or a negative value on error.
  *
diff --git a/include/spi_flash.h b/include/spi_flash.h
index bfc59aa..1ff5af4 100644
--- a/include/spi_flash.h
+++ b/include/spi_flash.h
@@ -1,7 +1,8 @@
 /*
- * Interface to SPI flash
+ * Common SPI flash Interface
  *
  * Copyright (C) 2008 Atmel Corporation
+ * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc.
  *
  * See file CREDITS for list of people who contributed to this
  * project.
@@ -10,6 +11,7 @@
  * modify it under the terms of the GNU General Public License
  * version 2 as published by the Free Software Foundation. 
  */
+
 #ifndef _SPI_FLASH_H_
 #define _SPI_FLASH_H_
 
@@ -17,75 +19,52 @@
 #include <linux/types.h>
 #include <linux/compiler.h>
 
+/**
+ * struct spi_flash - SPI flash structure
+ *
+ * @spi:		SPI slave
+ * @name:		Name of SPI flash
+ * @size:		Total flash size
+ * @page_size:		Write (page) size
+ * @sector_size:	Sector size
+ * @erase_size:		Erase size
+ * @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
+ * @memory_map:		Address of read-only SPI flash access
+ * @read:		Flash read ops: Read len bytes at offset into buf
+ *			Supported cmds: Fast Array Read
+ * @write:		Flash write ops: Write len bytes from buf into offeset
+ *			Supported cmds: Page Program
+ * @erase:		Flash erase ops: Erase len bytes from offset
+ *			Supported cmds: Sector erase 4K, 32K, 64K
+ * return 0 - Sucess, 1 - Failure
+ */
 struct spi_flash {
 	struct spi_slave *spi;
-
-	const char	*name;
+	const char *name;
 
-	/* Total flash size */
-	u32		size;
-	/* Write (page) size */
-	u32		page_size;
-	/* Erase (sector) size */
-	u32		sector_size;
+	u32 size;
+	u32 page_size;
+	u32 sector_size;
+	u32 erase_size;
 #ifdef CONFIG_SPI_FLASH_BAR
-	/* Bank read cmd */
-	u8		bank_read_cmd;
-	/* Bank write cmd */
-	u8		bank_write_cmd;
-	/* Current flash bank */
-	u8		bank_curr;
+	u8 bank_read_cmd;
+	u8 bank_write_cmd;
+	u8 bank_curr;
 #endif
-	/* Poll cmd - for flash erase/program */
-	u8		poll_cmd;
+	u8 poll_cmd;
+	u8 erase_cmd;
 
-	void *memory_map;	/* Address of read-only SPI flash access */
-	int		(*read)(struct spi_flash *flash, u32 offset,
-				size_t len, void *buf);
-	int		(*write)(struct spi_flash *flash, u32 offset,
-				size_t len, const void *buf);
-	int		(*erase)(struct spi_flash *flash, u32 offset,
-				size_t len);
+	void *memory_map;
+	int (*read)(struct spi_flash *flash, u32 offset, size_t len, void *buf);
+	int (*write)(struct spi_flash *flash, u32 offset, size_t len,
+			const void *buf);
+	int (*erase)(struct spi_flash *flash, u32 offset, size_t len);
 };
 
-/**
- * spi_flash_do_alloc - Allocate a new spi flash structure
- *
- * The structure is allocated and cleared with default values for
- * read, write and erase, which the caller can modify. The caller must set
- * up size, page_size and sector_size.
- *
- * Use the helper macro spi_flash_alloc() to call this.
- *
- * @offset: Offset of struct spi_slave within slave structure
- * @size: Size of slave structure
- * @spi: SPI slave
- * @name: Name of SPI flash device
- */
-void *spi_flash_do_alloc(int offset, int size, struct spi_slave *spi,
-			 const char *name);
-
-/**
- * spi_flash_alloc - Allocate a new SPI flash structure
- *
- * @_struct: Name of structure to allocate (e.g. struct ramtron_spi_fram). This
- *	structure must contain a member 'struct spi_flash *flash'.
- * @spi: SPI slave
- * @name: Name of SPI flash device
- */
-#define spi_flash_alloc(_struct, spi, name) \
-	spi_flash_do_alloc(offsetof(_struct, flash), sizeof(_struct), \
-				spi, name)
-
-/**
- * spi_flash_alloc_base - Allocate a new SPI flash structure with no private data
- *
- * @spi: SPI slave
- * @name: Name of SPI flash device
- */
-#define spi_flash_alloc_base(spi, name) \
-	spi_flash_do_alloc(0, sizeof(struct spi_flash), spi, name)
-
 struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
 		unsigned int max_hz, unsigned int spi_mode);
 void spi_flash_free(struct spi_flash *flash);