diff mbox

[U-Boot,v2,03/12] spi: sf: Support byte program for sst spi flash

Message ID 1414832035-13456-1-git-send-email-bmeng.cn@gmail.com
State Superseded
Delegated to: Jagannadha Sutradharudu Teki
Headers show

Commit Message

Bin Meng Nov. 1, 2014, 8:53 a.m. UTC
Currently if SST flash advertises SST_WP flag in the params table
the word program command (ADh) with auto address increment will be
used for the flash write op. However some SPI controllers do not
support the word program command (like the Intel ICH 7), the byte
programm command (02h) has to be used.

A new TX operation mode SPI_OPM_TX_BP is introduced for such SPI
controller to use byte program op for SST flash.

Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
Acked-by: Simon Glass <sjg@chromium.org>
Tested-by: Simon Glass <sjg@chromium.org>
---
 drivers/mtd/spi/sf_internal.h |  2 ++
 drivers/mtd/spi/sf_ops.c      | 31 +++++++++++++++++++++++++++++++
 drivers/mtd/spi/sf_probe.c    |  8 ++++++--
 drivers/spi/ich.c             |  9 +++++++--
 include/spi.h                 |  1 +
 5 files changed, 47 insertions(+), 4 deletions(-)

Comments

Jagan Teki Dec. 8, 2014, 6:04 p.m. UTC | #1
Hi Bin,

On 1 November 2014 at 14:23, Bin Meng <bmeng.cn@gmail.com> wrote:
> Currently if SST flash advertises SST_WP flag in the params table
> the word program command (ADh) with auto address increment will be
> used for the flash write op. However some SPI controllers do not
> support the word program command (like the Intel ICH 7), the byte
> programm command (02h) has to be used.
>
> A new TX operation mode SPI_OPM_TX_BP is introduced for such SPI
> controller to use byte program op for SST flash.

We have SST_WP which is word program - for specific flash's (not for
controller specific
at-least from params data)

Which is this SST_BP relies for ? controller or specific flash ?

>
> Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
> Acked-by: Simon Glass <sjg@chromium.org>
> Tested-by: Simon Glass <sjg@chromium.org>
> ---
>  drivers/mtd/spi/sf_internal.h |  2 ++
>  drivers/mtd/spi/sf_ops.c      | 31 +++++++++++++++++++++++++++++++
>  drivers/mtd/spi/sf_probe.c    |  8 ++++++--
>  drivers/spi/ich.c             |  9 +++++++--
>  include/spi.h                 |  1 +
>  5 files changed, 47 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h
> index 5b7670c..f519060 100644
> --- a/drivers/mtd/spi/sf_internal.h
> +++ b/drivers/mtd/spi/sf_internal.h
> @@ -107,6 +107,8 @@ enum {
>
>  int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len,
>                 const void *buf);
> +int sst_write_bp(struct spi_flash *flash, u32 offset, size_t len,
> +               const void *buf);
>  #endif
>
>  /**
> diff --git a/drivers/mtd/spi/sf_ops.c b/drivers/mtd/spi/sf_ops.c
> index 85cf22d..3703acb 100644
> --- a/drivers/mtd/spi/sf_ops.c
> +++ b/drivers/mtd/spi/sf_ops.c
> @@ -516,4 +516,35 @@ int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len,
>         spi_release_bus(flash->spi);
>         return ret;
>  }
> +
> +int sst_write_bp(struct spi_flash *flash, u32 offset, size_t len,
> +               const void *buf)
> +{
> +       size_t actual;
> +       int ret;
> +
> +       ret = spi_claim_bus(flash->spi);
> +       if (ret) {
> +               debug("SF: Unable to claim SPI bus\n");
> +               return ret;
> +       }
> +
> +       for (actual = 0; actual < len; actual++) {
> +               ret = sst_byte_write(flash, offset, buf + actual);
> +               if (ret) {
> +                       debug("SF: sst byte program failed\n");
> +                       break;
> +               }
> +               offset++;
> +       }
> +
> +       if (!ret)
> +               ret = spi_flash_cmd_write_disable(flash);
> +
> +       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
> index 2636426..b7ff63f 100644
> --- a/drivers/mtd/spi/sf_probe.c
> +++ b/drivers/mtd/spi/sf_probe.c
> @@ -135,8 +135,12 @@ static int spi_flash_validate_params(struct spi_slave *spi, u8 *idcode,
>  #ifndef CONFIG_DM_SPI_FLASH
>         flash->write = spi_flash_cmd_write_ops;
>  #if defined(CONFIG_SPI_FLASH_SST)
> -       if (params->flags & SST_WP)
> -               flash->write = sst_write_wp;
> +       if (params->flags & SST_WP) {
> +               if (flash->spi->op_mode_tx & SPI_OPM_TX_BP)
> +                       flash->write = sst_write_bp;
> +               else
> +                       flash->write = sst_write_wp;
> +       }
>  #endif
>         flash->erase = spi_flash_cmd_erase_ops;
>         flash->read = spi_flash_cmd_read_ops;
> diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c
> index b356411..16730ec 100644
> --- a/drivers/spi/ich.c
> +++ b/drivers/spi/ich.c
> @@ -141,9 +141,14 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
>         ich->slave.max_write_size = ctlr.databytes;
>         ich->speed = max_hz;
>
> -       /* ICH 7 SPI controller only supports array read command */
> -       if (ctlr.ich_version == 7)
> +       /*
> +        * ICH 7 SPI controller only supports array read command
> +        * and byte program command for SST flash
> +        */
> +       if (ctlr.ich_version == 7) {
>                 ich->slave.op_mode_rx = SPI_OPM_RX_AS;
> +               ich->slave.op_mode_tx = SPI_OPM_TX_BP;
> +       }
>
>         return &ich->slave;
>  }
> diff --git a/include/spi.h b/include/spi.h
> index aa0a48e..60202ee 100644
> --- a/include/spi.h
> +++ b/include/spi.h
> @@ -34,6 +34,7 @@
>
>  /* SPI TX operation modes */
>  #define SPI_OPM_TX_QPP         (1 << 0)
> +#define SPI_OPM_TX_BP          (1 << 1)
>
>  /* SPI RX operation modes */
>  #define SPI_OPM_RX_AS          (1 << 0)
> --
> 1.8.2.1
>
Bin Meng Dec. 9, 2014, 2:31 a.m. UTC | #2
Hi Jagan,

On Tue, Dec 9, 2014 at 2:04 AM, Jagan Teki <jagannadh.teki@gmail.com> wrote:
> Hi Bin,
>
> On 1 November 2014 at 14:23, Bin Meng <bmeng.cn@gmail.com> wrote:
>> Currently if SST flash advertises SST_WP flag in the params table
>> the word program command (ADh) with auto address increment will be
>> used for the flash write op. However some SPI controllers do not
>> support the word program command (like the Intel ICH 7), the byte
>> programm command (02h) has to be used.
>>
>> A new TX operation mode SPI_OPM_TX_BP is introduced for such SPI
>> controller to use byte program op for SST flash.
>
> We have SST_WP which is word program - for specific flash's (not for
> controller specific
> at-least from params data)
>
> Which is this SST_BP relies for ? controller or specific flash ?
>

SST_BP is flash specific. In current flash params table, I checked
every flash datasheet and found that when an SST flash supports WP, it
also supports BP. I believe the WP and BP are companion commands. When
an SST flash does not support BP/WP, it supports the page program
(02h) which uses the same command code as BP. And the page program
(02h) is the command selected by U-Boot for SST flashes which do not
have SST_WP flag.

However some controllers do not support WP, so that we need the SST_BP
flag to let U-Boot selects BP for such controllers, which is what my
patch tries to fix.

[snip]

Regards,
Bin
diff mbox

Patch

diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h
index 5b7670c..f519060 100644
--- a/drivers/mtd/spi/sf_internal.h
+++ b/drivers/mtd/spi/sf_internal.h
@@ -107,6 +107,8 @@  enum {
 
 int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len,
 		const void *buf);
+int sst_write_bp(struct spi_flash *flash, u32 offset, size_t len,
+		const void *buf);
 #endif
 
 /**
diff --git a/drivers/mtd/spi/sf_ops.c b/drivers/mtd/spi/sf_ops.c
index 85cf22d..3703acb 100644
--- a/drivers/mtd/spi/sf_ops.c
+++ b/drivers/mtd/spi/sf_ops.c
@@ -516,4 +516,35 @@  int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len,
 	spi_release_bus(flash->spi);
 	return ret;
 }
+
+int sst_write_bp(struct spi_flash *flash, u32 offset, size_t len,
+		const void *buf)
+{
+	size_t actual;
+	int ret;
+
+	ret = spi_claim_bus(flash->spi);
+	if (ret) {
+		debug("SF: Unable to claim SPI bus\n");
+		return ret;
+	}
+
+	for (actual = 0; actual < len; actual++) {
+		ret = sst_byte_write(flash, offset, buf + actual);
+		if (ret) {
+			debug("SF: sst byte program failed\n");
+			break;
+		}
+		offset++;
+	}
+
+	if (!ret)
+		ret = spi_flash_cmd_write_disable(flash);
+
+	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
index 2636426..b7ff63f 100644
--- a/drivers/mtd/spi/sf_probe.c
+++ b/drivers/mtd/spi/sf_probe.c
@@ -135,8 +135,12 @@  static int spi_flash_validate_params(struct spi_slave *spi, u8 *idcode,
 #ifndef CONFIG_DM_SPI_FLASH
 	flash->write = spi_flash_cmd_write_ops;
 #if defined(CONFIG_SPI_FLASH_SST)
-	if (params->flags & SST_WP)
-		flash->write = sst_write_wp;
+	if (params->flags & SST_WP) {
+		if (flash->spi->op_mode_tx & SPI_OPM_TX_BP)
+			flash->write = sst_write_bp;
+		else
+			flash->write = sst_write_wp;
+	}
 #endif
 	flash->erase = spi_flash_cmd_erase_ops;
 	flash->read = spi_flash_cmd_read_ops;
diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c
index b356411..16730ec 100644
--- a/drivers/spi/ich.c
+++ b/drivers/spi/ich.c
@@ -141,9 +141,14 @@  struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
 	ich->slave.max_write_size = ctlr.databytes;
 	ich->speed = max_hz;
 
-	/* ICH 7 SPI controller only supports array read command */
-	if (ctlr.ich_version == 7)
+	/*
+	 * ICH 7 SPI controller only supports array read command
+	 * and byte program command for SST flash
+	 */
+	if (ctlr.ich_version == 7) {
 		ich->slave.op_mode_rx = SPI_OPM_RX_AS;
+		ich->slave.op_mode_tx = SPI_OPM_TX_BP;
+	}
 
 	return &ich->slave;
 }
diff --git a/include/spi.h b/include/spi.h
index aa0a48e..60202ee 100644
--- a/include/spi.h
+++ b/include/spi.h
@@ -34,6 +34,7 @@ 
 
 /* SPI TX operation modes */
 #define SPI_OPM_TX_QPP		(1 << 0)
+#define SPI_OPM_TX_BP		(1 << 1)
 
 /* SPI RX operation modes */
 #define SPI_OPM_RX_AS		(1 << 0)