Message ID | 1414832035-13456-1-git-send-email-bmeng.cn@gmail.com |
---|---|
State | Superseded |
Delegated to: | Jagannadha Sutradharudu Teki |
Headers | show |
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 >
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 --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)