Merge branch 'master' of git://git.denx.de/u-boot-spi
diff --git a/README b/README
index a70af98..ee65fdb 100644
--- a/README
+++ b/README
@@ -3096,17 +3096,6 @@
 		memories can be connected with a given cs line.
 		Currently Xilinx Zynq qspi supports these type of connections.
 
-		CONFIG_SYS_SPI_ST_ENABLE_WP_PIN
-		enable the W#/Vpp signal to disable writing to the status
-		register on ST MICRON flashes like the N25Q128.
-		The status register write enable/disable bit, combined with
-		the W#/VPP signal provides hardware data protection for the
-		device as follows: When the enable/disable bit is set to 1,
-		and the W#/VPP signal is driven LOW, the status register
-		nonvolatile bits become read-only and the WRITE STATUS REGISTER
-		operation will not execute. The only way to exit this
-		hardware-protected mode is to drive W#/VPP HIGH.
-
 - SystemACE Support:
 		CONFIG_SYSTEMACE
 
diff --git a/common/cmd_sf.c b/common/cmd_sf.c
index 6aabf39..342021d 100644
--- a/common/cmd_sf.c
+++ b/common/cmd_sf.c
@@ -164,6 +164,8 @@
 static const char *spi_flash_update_block(struct spi_flash *flash, u32 offset,
 		size_t len, const char *buf, char *cmp_buf, size_t *skipped)
 {
+	char *ptr = (char *)buf;
+
 	debug("offset=%#x, sector_size=%#x, len=%#zx\n",
 	      offset, flash->sector_size, len);
 	/* Read the entire sector so to allow for rewriting */
@@ -179,16 +181,14 @@
 	/* Erase the entire sector */
 	if (spi_flash_erase(flash, offset, flash->sector_size))
 		return "erase";
-	/* Write the initial part of the block from the source */
-	if (spi_flash_write(flash, offset, len, buf))
-		return "write";
-	/* If it's a partial sector, rewrite the existing part */
+	/* If it's a partial sector, copy the data into the temp-buffer */
 	if (len != flash->sector_size) {
-		/* Rewrite the original data to the end of the sector */
-		if (spi_flash_write(flash, offset + len,
-				    flash->sector_size - len, &cmp_buf[len]))
-			return "write";
+		memcpy(cmp_buf, buf, len);
+		ptr = cmp_buf;
 	}
+	/* Write one complete sector */
+	if (spi_flash_write(flash, offset, flash->sector_size, ptr))
+		return "write";
 
 	return NULL;
 }
diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h
index 785f7a9..4158e13 100644
--- a/drivers/mtd/spi/sf_internal.h
+++ b/drivers/mtd/spi/sf_internal.h
@@ -97,10 +97,6 @@
 #define STATUS_QEB_MXIC		(1 << 6)
 #define STATUS_PEC			(1 << 7)
 
-#ifdef CONFIG_SYS_SPI_ST_ENABLE_WP_PIN
-#define STATUS_SRWD			(1 << 7) /* SR write protect */
-#endif
-
 /* Flash timeout values */
 #define SPI_FLASH_PROG_TIMEOUT		(2 * CONFIG_SYS_HZ)
 #define SPI_FLASH_PAGE_ERASE_TIMEOUT		(5 * CONFIG_SYS_HZ)
@@ -123,7 +119,8 @@
  * @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
+ * @sector_size:	Isn't necessarily a sector size from vendor,
+ *			the size listed here is what works with CMD_ERASE_64K
  * @nr_sectors:	No.of sectors on this device
  * @e_rd_cmd:		Enum list for read commands
  * @flags:		Important param, for flash specific behaviour
diff --git a/drivers/mtd/spi/sf_ops.c b/drivers/mtd/spi/sf_ops.c
index 34bc54e..38592f5 100644
--- a/drivers/mtd/spi/sf_ops.c
+++ b/drivers/mtd/spi/sf_ops.c
@@ -154,21 +154,17 @@
 }
 #endif
 
-int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout)
+static int spi_flash_poll_status(struct spi_slave *spi, unsigned long timeout,
+				 u8 cmd, u8 poll_bit)
 {
-	struct spi_slave *spi = flash->spi;
 	unsigned long timebase;
 	unsigned long flags = SPI_XFER_BEGIN;
 	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;
+	if (cmd == CMD_FLAG_STATUS)
 		check_status = poll_bit;
-	}
 
 #ifdef CONFIG_SF_DUAL_FLASH
 	if (spi->flags & SPI_XFER_U_PAGE)
@@ -204,6 +200,28 @@
 	return -1;
 }
 
+int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout)
+{
+	struct spi_slave *spi = flash->spi;
+	int ret;
+	u8 poll_bit = STATUS_WIP;
+	u8 cmd = CMD_READ_STATUS;
+
+	ret = spi_flash_poll_status(spi, timeout, cmd, poll_bit);
+	if (ret < 0)
+		return ret;
+
+	if (flash->poll_cmd == CMD_FLAG_STATUS) {
+		poll_bit = STATUS_PEC;
+		cmd = CMD_FLAG_STATUS;
+		ret = spi_flash_poll_status(spi, timeout, cmd, poll_bit);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+
 int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd,
 		size_t cmd_len, const void *buf, size_t buf_len)
 {
diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c
index d19138d..201471c 100644
--- a/drivers/mtd/spi/sf_probe.c
+++ b/drivers/mtd/spi/sf_probe.c
@@ -132,6 +132,9 @@
 	flash->name = params->name;
 	flash->memory_map = spi->memory_map;
 	flash->dual_flash = flash->spi->option;
+#ifdef CONFIG_DM_SPI_FLASH
+	flash->flags = params->flags;
+#endif
 
 	/* Assign spi_flash ops */
 #ifndef CONFIG_DM_SPI_FLASH
@@ -184,6 +187,9 @@
 		flash->erase_size = flash->sector_size;
 	}
 
+	/* Now erase size becomes valid sector size */
+	flash->sector_size = flash->erase_size;
+
 	/* Look for the fastest read cmd */
 	cmd = fls(params->e_rd_cmd & flash->spi->op_mode_rx);
 	if (cmd) {
@@ -288,34 +294,6 @@
 }
 #endif /* CONFIG_OF_CONTROL */
 
-#ifdef CONFIG_SYS_SPI_ST_ENABLE_WP_PIN
-/* enable the W#/Vpp signal to disable writing to the status register */
-static int spi_enable_wp_pin(struct spi_flash *flash)
-{
-	u8 status;
-	int ret;
-
-	ret = spi_flash_cmd_read_status(flash, &status);
-	if (ret < 0)
-		return ret;
-
-	ret = spi_flash_cmd_write_status(flash, STATUS_SRWD);
-	if (ret < 0)
-		return ret;
-
-	ret = spi_flash_cmd_write_disable(flash);
-	if (ret < 0)
-		return ret;
-
-	return 0;
-}
-#else
-static int spi_enable_wp_pin(struct spi_flash *flash)
-{
-	return 0;
-}
-#endif
-
 /**
  * spi_flash_probe_slave() - Probe for a SPI flash device on a bus
  *
@@ -394,8 +372,6 @@
 		puts(" Full access #define CONFIG_SPI_FLASH_BAR\n");
 	}
 #endif
-	if (spi_enable_wp_pin(flash))
-		puts("Enable WP pin failed\n");
 
 	/* Release spi bus */
 	spi_release_bus(spi);
@@ -434,6 +410,8 @@
 	struct spi_slave *bus;
 
 	bus = spi_setup_slave(busnum, cs, max_hz, spi_mode);
+	if (!bus)
+		return NULL;
 	return spi_flash_probe_tail(bus);
 }
 
@@ -444,6 +422,8 @@
 	struct spi_slave *bus;
 
 	bus = spi_setup_slave_fdt(blob, slave_node, spi_node);
+	if (!bus)
+		return NULL;
 	return spi_flash_probe_tail(bus);
 }
 #endif
@@ -469,6 +449,15 @@
 {
 	struct spi_flash *flash = dev_get_uclass_priv(dev);
 
+#if defined(CONFIG_SPI_FLASH_SST)
+	if (flash->flags & SST_WR) {
+		if (flash->spi->op_mode_tx & SPI_OPM_TX_BP)
+			return sst_write_bp(flash, offset, len, buf);
+		else
+			return sst_write_wp(flash, offset, len, buf);
+	}
+#endif
+
 	return spi_flash_cmd_write_ops(flash, offset, len, buf);
 }
 
diff --git a/drivers/spi/exynos_spi.c b/drivers/spi/exynos_spi.c
index a46d8c1..67f6b2d 100644
--- a/drivers/spi/exynos_spi.c
+++ b/drivers/spi/exynos_spi.c
@@ -296,8 +296,9 @@
 	return 0;
 }
 
-static int exynos_spi_claim_bus(struct udevice *bus)
+static int exynos_spi_claim_bus(struct udevice *dev)
 {
+	struct udevice *bus = dev->parent;
 	struct exynos_spi_priv *priv = dev_get_priv(bus);
 
 	exynos_pinmux_config(priv->periph_id, PINMUX_FLAG_NONE);
@@ -308,8 +309,9 @@
 	return 0;
 }
 
-static int exynos_spi_release_bus(struct udevice *bus)
+static int exynos_spi_release_bus(struct udevice *dev)
 {
+	struct udevice *bus = dev->parent;
 	struct exynos_spi_priv *priv = dev_get_priv(bus);
 
 	spi_flush_fifo(priv->regs);
diff --git a/drivers/spi/omap3_spi.c b/drivers/spi/omap3_spi.c
index 651e46e..85f9e85 100644
--- a/drivers/spi/omap3_spi.c
+++ b/drivers/spi/omap3_spi.c
@@ -20,7 +20,7 @@
 #include <asm/io.h>
 #include "omap3_spi.h"
 
-#define SPI_WAIT_TIMEOUT 3000000
+#define SPI_WAIT_TIMEOUT 10
 
 static void spi_reset(struct omap3_spi_slave *ds)
 {
@@ -227,7 +227,7 @@
 {
 	struct omap3_spi_slave *ds = to_omap3_spi(slave);
 	int i;
-	int timeout = SPI_WAIT_TIMEOUT;
+	ulong start;
 	int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf);
 
 	/* Enable the channel */
@@ -241,9 +241,10 @@
 
 	for (i = 0; i < len; i++) {
 		/* wait till TX register is empty (TXS == 1) */
+		start = get_timer(0);
 		while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) &
 			 OMAP3_MCSPI_CHSTAT_TXS)) {
-			if (--timeout <= 0) {
+			if (get_timer(start) > SPI_WAIT_TIMEOUT) {
 				printf("SPI TXS timed out, status=0x%08x\n",
 				       readl(&ds->regs->channel[ds->slave.cs].chstat));
 				return -1;
@@ -280,7 +281,7 @@
 {
 	struct omap3_spi_slave *ds = to_omap3_spi(slave);
 	int i;
-	int timeout = SPI_WAIT_TIMEOUT;
+	ulong start;
 	int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf);
 
 	/* Enable the channel */
@@ -295,10 +296,11 @@
 	writel(0, &ds->regs->channel[ds->slave.cs].tx);
 
 	for (i = 0; i < len; i++) {
+		start = get_timer(0);
 		/* Wait till RX register contains data (RXS == 1) */
 		while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) &
 			 OMAP3_MCSPI_CHSTAT_RXS)) {
-			if (--timeout <= 0) {
+			if (get_timer(start) > SPI_WAIT_TIMEOUT) {
 				printf("SPI RXS timed out, status=0x%08x\n",
 				       readl(&ds->regs->channel[ds->slave.cs].chstat));
 				return -1;
@@ -332,7 +334,7 @@
 		   const void *txp, void *rxp, unsigned long flags)
 {
 	struct omap3_spi_slave *ds = to_omap3_spi(slave);
-	int timeout = SPI_WAIT_TIMEOUT;
+	ulong start;
 	int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf);
 	int irqstatus = readl(&ds->regs->irqstatus);
 	int i=0;
@@ -350,9 +352,10 @@
 	for (i=0; i < len; i++){
 		/* Write: wait for TX empty (TXS == 1)*/
 		irqstatus |= (1<< (4*(ds->slave.bus)));
+		start = get_timer(0);
 		while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) &
 			 OMAP3_MCSPI_CHSTAT_TXS)) {
-			if (--timeout <= 0) {
+			if (get_timer(start) > SPI_WAIT_TIMEOUT) {
 				printf("SPI TXS timed out, status=0x%08x\n",
 				       readl(&ds->regs->channel[ds->slave.cs].chstat));
 				return -1;
@@ -368,9 +371,10 @@
 			writel(((u8 *)txp)[i], tx);
 
 		/*Read: wait for RX containing data (RXS == 1)*/
+		start = get_timer(0);
 		while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) &
 			 OMAP3_MCSPI_CHSTAT_RXS)) {
-			if (--timeout <= 0) {
+			if (get_timer(start) > SPI_WAIT_TIMEOUT) {
 				printf("SPI RXS timed out, status=0x%08x\n",
 				       readl(&ds->regs->channel[ds->slave.cs].chstat));
 				return -1;
diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c
index 866c48f..83fe8e0 100644
--- a/drivers/spi/spi-uclass.c
+++ b/drivers/spi/spi-uclass.c
@@ -67,7 +67,7 @@
 	if (ret)
 		return ret;
 
-	return ops->claim_bus ? ops->claim_bus(bus) : 0;
+	return ops->claim_bus ? ops->claim_bus(dev) : 0;
 }
 
 void spi_release_bus(struct spi_slave *slave)
@@ -77,7 +77,7 @@
 	struct dm_spi_ops *ops = spi_get_ops(bus);
 
 	if (ops->release_bus)
-		ops->release_bus(bus);
+		ops->release_bus(dev);
 }
 
 int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
diff --git a/drivers/spi/tegra114_spi.c b/drivers/spi/tegra114_spi.c
index 53ff9ea..4bec663 100644
--- a/drivers/spi/tegra114_spi.c
+++ b/drivers/spi/tegra114_spi.c
@@ -153,8 +153,9 @@
 	return 0;
 }
 
-static int tegra114_spi_claim_bus(struct udevice *bus)
+static int tegra114_spi_claim_bus(struct udevice *dev)
 {
+	struct udevice *bus = dev->parent;
 	struct tegra114_spi_priv *priv = dev_get_priv(bus);
 	struct spi_regs *regs = priv->regs;
 
diff --git a/drivers/spi/tegra20_sflash.c b/drivers/spi/tegra20_sflash.c
index 78c74cd..82c1b84 100644
--- a/drivers/spi/tegra20_sflash.c
+++ b/drivers/spi/tegra20_sflash.c
@@ -125,8 +125,9 @@
 	return 0;
 }
 
-static int tegra20_sflash_claim_bus(struct udevice *bus)
+static int tegra20_sflash_claim_bus(struct udevice *dev)
 {
+	struct udevice *bus = dev->parent;
 	struct tegra20_sflash_priv *priv = dev_get_priv(bus);
 	struct spi_regs *regs = priv->regs;
 	u32 reg;
diff --git a/drivers/spi/tegra20_slink.c b/drivers/spi/tegra20_slink.c
index 597d6ad..f6fb89b 100644
--- a/drivers/spi/tegra20_slink.c
+++ b/drivers/spi/tegra20_slink.c
@@ -141,8 +141,9 @@
 	return 0;
 }
 
-static int tegra30_spi_claim_bus(struct udevice *bus)
+static int tegra30_spi_claim_bus(struct udevice *dev)
 {
+	struct udevice *bus = dev->parent;
 	struct tegra30_spi_priv *priv = dev_get_priv(bus);
 	struct spi_regs *regs = priv->regs;
 	u32 reg;
diff --git a/drivers/spi/zynq_spi.c b/drivers/spi/zynq_spi.c
index 5da8759..e9129da 100644
--- a/drivers/spi/zynq_spi.c
+++ b/drivers/spi/zynq_spi.c
@@ -227,9 +227,6 @@
 	debug("spi_xfer: bus:%i cs:%i bitlen:%i len:%i flags:%lx\n",
 	      slave->bus, slave->cs, bitlen, len, flags);
 
-	if (bitlen == 0)
-		return -1;
-
 	if (bitlen % 8) {
 		debug("spi_xfer: Non byte aligned SPI transfer\n");
 		return -1;
diff --git a/include/spi.h b/include/spi.h
index c58e453..9495ca5 100644
--- a/include/spi.h
+++ b/include/spi.h
@@ -38,11 +38,12 @@
 
 /* SPI RX operation modes */
 #define SPI_OPM_RX_AS		(1 << 0)
-#define SPI_OPM_RX_DOUT	(1 << 1)
-#define SPI_OPM_RX_DIO		(1 << 2)
-#define SPI_OPM_RX_QOF		(1 << 3)
-#define SPI_OPM_RX_QIOF	(1 << 4)
-#define SPI_OPM_RX_EXTN	(SPI_OPM_RX_AS | SPI_OPM_RX_DOUT | \
+#define SPI_OPM_RX_AF		(1 << 1)
+#define SPI_OPM_RX_DOUT		(1 << 2)
+#define SPI_OPM_RX_DIO		(1 << 3)
+#define SPI_OPM_RX_QOF		(1 << 4)
+#define SPI_OPM_RX_QIOF		(1 << 5)
+#define SPI_OPM_RX_EXTN	(SPI_OPM_RX_AS | SPI_OPM_RX_AF | SPI_OPM_RX_DOUT | \
 				SPI_OPM_RX_DIO | SPI_OPM_RX_QOF | \
 				SPI_OPM_RX_QIOF)
 
@@ -385,12 +386,12 @@
 	 * allowed to claim the same bus for several slaves without releasing
 	 * the bus in between.
 	 *
-	 * @bus:	The SPI slave
+	 * @dev:	The SPI slave
 	 *
 	 * Returns: 0 if the bus was claimed successfully, or a negative value
 	 * if it wasn't.
 	 */
-	int (*claim_bus)(struct udevice *bus);
+	int (*claim_bus)(struct udevice *dev);
 
 	/**
 	 * Release the SPI bus
@@ -399,9 +400,9 @@
 	 * all transfers have finished. It may disable any SPI hardware as
 	 * appropriate.
 	 *
-	 * @bus:	The SPI slave
+	 * @dev:	The SPI slave
 	 */
-	int (*release_bus)(struct udevice *bus);
+	int (*release_bus)(struct udevice *dev);
 
 	/**
 	 * Set the word length for SPI transactions
@@ -413,7 +414,7 @@
 	 *
 	 * Returns: 0 on success, -ve on failure.
 	 */
-	int (*set_wordlen)(struct udevice *bus, unsigned int wordlen);
+	int (*set_wordlen)(struct udevice *dev, unsigned int wordlen);
 
 	/**
 	 * SPI transfer
diff --git a/include/spi_flash.h b/include/spi_flash.h
index 218283f..f2814ef 100644
--- a/include/spi_flash.h
+++ b/include/spi_flash.h
@@ -62,11 +62,10 @@
  * return 0 - Success, 1 - Failure
  */
 struct spi_flash {
+	struct spi_slave *spi;
 #ifdef CONFIG_DM_SPI_FLASH
-	struct spi_slave *spi;
 	struct udevice *dev;
-#else
-	struct spi_slave *spi;
+	u16 flags;
 #endif
 	const char *name;
 	u8 dual_flash;
@@ -91,13 +90,13 @@
 #ifndef CONFIG_DM_SPI_FLASH
 	/*
 	 * These are not strictly needed for driver model, but keep them here
-	 * whilt the transition is in progress.
+	 * while the transition is in progress.
 	 *
 	 * Normally each driver would provide its own operations, but for
 	 * SPI flash most chips use the same algorithms. One approach is
 	 * to create a 'common' SPI flash device which knows how to talk
 	 * to most devices, and then allow other drivers to be used instead
-	 * if requird, perhaps with a way of scanning through the list to
+	 * if required, perhaps with a way of scanning through the list to
 	 * find the driver that matches the device.
 	 */
 	int (*read)(struct spi_flash *flash, u32 offset, size_t len, void *buf);