diff mbox

[U-Boot,6/6] sf: Update spi_flash_cmd_wait_ready

Message ID 1439714629-6003-7-git-send-email-jteki@openedev.com
State Superseded
Delegated to: Jagannadha Sutradharudu Teki
Headers show

Commit Message

Jagan Teki Aug. 16, 2015, 8:43 a.m. UTC
Current flash wait_ready logic is not modular to add new
register status check, hence few of the logic is used from
Linux spi-nor framework.

Below are the sf speed runs with 'sf update' on whole flash, 16MiB.

=> sf update 0x100 0x0 0x1000000
device 0 whole chip
16777216 bytes written, 0 bytes skipped in 61.784s, speed 279620 B/s

=> sf update 0x100 0x0 0x1000000
device 0 whole chip
16777216 bytes written, 0 bytes skipped in 61.276s, speed 284359 B/s

Signed-off-by: Jagan Teki <jteki@openedev.com>
Cc: Simon Glass <sjg@chromium.org>
Cc: Marek Vasut <marex@denx.de>
Cc: Michal Simek <michal.simek@xilinx.com>
Cc: Siva Durga Prasad Paladugu <sivadur@xilinx.com>
Cc: Stefan Roese <sr@denx.de>
Cc: Tom Warren <twarren@nvidia.com>
Cc: Bin Meng <bmeng.cn@gmail.com>
Cc: Tom Rini <trini@konsulko.com>
Tested-by: Jagan Teki <jteki@openedev.com>
---
 drivers/mtd/spi/sf_internal.h |   1 +
 drivers/mtd/spi/sf_ops.c      | 110 ++++++++++++++++++++++++------------------
 drivers/mtd/spi/sf_probe.c    |   4 +-
 include/spi_flash.h           |   2 -
 4 files changed, 64 insertions(+), 53 deletions(-)

Comments

Marek Vasut Aug. 16, 2015, 4:57 p.m. UTC | #1
On Sunday, August 16, 2015 at 10:43:49 AM, Jagan Teki wrote:
> Current flash wait_ready logic is not modular to add new
> register status check, hence few of the logic is used from
> Linux spi-nor framework.
> 
> Below are the sf speed runs with 'sf update' on whole flash, 16MiB.
> 
> => sf update 0x100 0x0 0x1000000
> device 0 whole chip
> 16777216 bytes written, 0 bytes skipped in 61.784s, speed 279620 B/s
> 
> => sf update 0x100 0x0 0x1000000
> device 0 whole chip
> 16777216 bytes written, 0 bytes skipped in 61.276s, speed 284359 B/s
> 
> Signed-off-by: Jagan Teki <jteki@openedev.com>
> Cc: Simon Glass <sjg@chromium.org>
> Cc: Marek Vasut <marex@denx.de>
> Cc: Michal Simek <michal.simek@xilinx.com>
> Cc: Siva Durga Prasad Paladugu <sivadur@xilinx.com>
> Cc: Stefan Roese <sr@denx.de>
> Cc: Tom Warren <twarren@nvidia.com>
> Cc: Bin Meng <bmeng.cn@gmail.com>
> Cc: Tom Rini <trini@konsulko.com>
> Tested-by: Jagan Teki <jteki@openedev.com>
> ---

Please split this into two patches, one which makes the code modular
and next one which adds new features (the FSR reading or whatever).

Best regards,
Marek Vasut
diff mbox

Patch

diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h
index e97c716..4ecfd0c 100644
--- a/drivers/mtd/spi/sf_internal.h
+++ b/drivers/mtd/spi/sf_internal.h
@@ -49,6 +49,7 @@  enum {
 
 enum spi_nor_option_flags {
 	SNOR_F_SST_WR		= (1 << 0),
+	SNOR_F_USE_FSR		= (1 << 1),
 };
 
 #define SPI_FLASH_3B_ADDR_LEN		3
diff --git a/drivers/mtd/spi/sf_ops.c b/drivers/mtd/spi/sf_ops.c
index f1be815..388fdd0 100644
--- a/drivers/mtd/spi/sf_ops.c
+++ b/drivers/mtd/spi/sf_ops.c
@@ -40,6 +40,21 @@  int spi_flash_cmd_read_status(struct spi_flash *flash, u8 *rs)
 	return 0;
 }
 
+static int read_fsr(struct spi_flash *flash, u8 *fsr)
+{
+	int ret;
+	u8 cmd;
+
+	cmd = CMD_FLAG_STATUS;
+	ret = spi_flash_read_common(flash, &cmd, 1, fsr, 1);
+	if (ret < 0) {
+		debug("SF: fail to read flag status register\n");
+		return ret;
+	}
+
+	return 0;
+}
+
 int spi_flash_cmd_write_status(struct spi_flash *flash, u8 ws)
 {
 	u8 cmd;
@@ -138,72 +153,71 @@  static void spi_flash_dual_flash(struct spi_flash *flash, u32 *addr)
 }
 #endif
 
-static int spi_flash_poll_status(struct spi_slave *spi, unsigned long timeout,
-				 u8 cmd, u8 poll_bit)
+static inline int spi_flash_sr_ready(struct spi_flash *flash)
 {
-	unsigned long timebase;
-	unsigned long flags = SPI_XFER_BEGIN;
+	u8 sr;
 	int ret;
-	u8 status;
-	u8 check_status = 0x0;
-
-	if (cmd == CMD_FLAG_STATUS)
-		check_status = poll_bit;
 
-#ifdef CONFIG_SF_DUAL_FLASH
-	if (spi->flags & SPI_XFER_U_PAGE)
-		flags |= SPI_XFER_U_PAGE;
-#endif
-	ret = spi_xfer(spi, 8, &cmd, NULL, flags);
-	if (ret) {
-		debug("SF: fail to read %s status register\n",
-		      cmd == CMD_READ_STATUS ? "read" : "flag");
+	ret = spi_flash_cmd_read_status(flash, &sr);
+	if (ret < 0)
 		return ret;
-	}
-
-	timebase = get_timer(0);
-	do {
-		WATCHDOG_RESET();
-
-		ret = spi_xfer(spi, 8, NULL, &status, 0);
-		if (ret)
-			return -1;
 
-		if ((status & poll_bit) == check_status)
-			break;
+	if (sr < 0)
+		return sr;
+	else
+		return !(sr & STATUS_WIP);
+}
 
-	} while (get_timer(timebase) < timeout);
+static inline int spi_flash_fsr_ready(struct spi_flash *flash)
+{
+	u8 fsr;
+	int ret;
 
-	spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END);
+	ret = read_fsr(flash, &fsr);
+	if (ret < 0)
+		return ret;
 
-	if ((status & poll_bit) == check_status)
-		return 0;
+	if (fsr < 0)
+		return fsr;
+	else
+		return fsr & STATUS_PEC;
+}
 
-	/* Timed out */
-	debug("SF: time out!\n");
-	return -1;
+static int spi_flash_ready(struct spi_flash *flash)
+{
+	int sr, fsr;
+	sr = spi_flash_sr_ready(flash);
+	if (sr < 0)
+		return sr;
+	fsr = flash->flags & SNOR_F_USE_FSR ? spi_flash_fsr_ready(flash) : 1;
+	if (fsr < 0)
+		return fsr;
+	return sr && fsr;
 }
 
-int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout)
+/*
+ * Service routine to read status register until ready, or timeout occurs.
+ * Returns non-zero if error.
+ */
+int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long deadline)
 {
-	struct spi_slave *spi = flash->spi;
-	int ret;
-	u8 poll_bit = STATUS_WIP;
-	u8 cmd = CMD_READ_STATUS;
+	int timeout, ret;
 
-	ret = spi_flash_poll_status(spi, timeout, cmd, poll_bit);
-	if (ret < 0)
-		return ret;
+	timeout = get_timer(0);
 
-	if (flash->poll_cmd == CMD_FLAG_STATUS) {
-		poll_bit = STATUS_PEC;
-		cmd = CMD_FLAG_STATUS;
-		ret = spi_flash_poll_status(spi, timeout, cmd, poll_bit);
+	while (get_timer(timeout) < deadline) {
+		ret = spi_flash_ready(flash);
 		if (ret < 0)
 			return ret;
+		if (ret)
+			return 0;
+
+		cond_resched();
 	}
 
-	return 0;
+	printf("SF: Timeout!\n");
+
+	return -ETIMEDOUT;
 }
 
 int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd,
diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c
index 1de2bbb..fb79b02 100644
--- a/drivers/mtd/spi/sf_probe.c
+++ b/drivers/mtd/spi/sf_probe.c
@@ -256,11 +256,9 @@  static int spi_flash_validate_params(struct spi_slave *spi, u8 *idcode,
 		flash->dummy_byte = 1;
 	}
 
-	/* Poll cmd selection */
-	flash->poll_cmd = CMD_READ_STATUS;
 #ifdef CONFIG_SPI_FLASH_STMICRO
 	if (params->flags & E_FSR)
-		flash->poll_cmd = CMD_FLAG_STATUS;
+		flash->flags |= SNOR_F_USE_FSR;
 #endif
 
 	/* Configure the BAR - discover bank cmds and read current bank */
diff --git a/include/spi_flash.h b/include/spi_flash.h
index 8d85468..4312d3d 100644
--- a/include/spi_flash.h
+++ b/include/spi_flash.h
@@ -49,7 +49,6 @@  struct spi_slave;
  * @bank_read_cmd:	Bank read cmd
  * @bank_write_cmd:	Bank write cmd
  * @bank_curr:		Current flash bank
- * @poll_cmd:		Poll cmd - for flash erase/program
  * @erase_cmd:		Erase cmd 4K, 32K, 64K
  * @read_cmd:		Read cmd - Array Fast, Extn read and quad read.
  * @write_cmd:		Write cmd - page and quad program.
@@ -82,7 +81,6 @@  struct spi_flash {
 	u8 bank_write_cmd;
 	u8 bank_curr;
 #endif
-	u8 poll_cmd;
 	u8 erase_cmd;
 	u8 read_cmd;
 	u8 write_cmd;