sst write operations can be changed based on the mode set from the controller with byte program or word program, so sync the similar code from legacy spi_flash.c and update accordingly with mtd operations.
Signed-off-by: Suneel Garapati <suneelgli...@gmail.com> Signed-off-by: Jagan Teki <ja...@amarulasolutions.com> --- drivers/mtd/spi-nor/spi-nor.c | 115 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 09fb8ca..cfd21fb 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -316,6 +316,113 @@ int spi_nor_mread(struct udevice *dev, loff_t from, size_t len, return ret; } +#ifdef CONFIG_SPI_NOR_SST +static int sst_byte_write(struct spi_nor *nor, u32 addr, const void *buf, + size_t *retlen) +{ + const struct spi_nor_ops *ops = spi_nor_get_ops(nor->dev); + int ret; + + ret = write_enable(nor->dev); + if (ret) + return ret; + + nor->program_opcode = SNOR_OP_BP; + + ret = ops->write(nor->dev, addr, 1, buf); + if (ret) + return ret; + + *retlen += 1; + + return spi_nor_wait_till_ready(nor->dev, SNOR_READY_WAIT_PROG); +} + +static int sst_mwrite_wp(struct udevice *dev, loff_t to, size_t len, + size_t *retlen, const u_char *buf) +{ + struct mtd_info *mtd = mtd_get_info(dev); + int devnum = mtd->devnum; + const struct spi_nor_ops *ops; + struct spi_nor *nor; + size_t actual; + int ret; + + nor = find_spi_nor_device(devnum); + if (!nor) + return -ENODEV; + ops = spi_nor_get_ops(nor->dev); + + /* If the data is not word aligned, write out leading single byte */ + actual = to % 2; + if (actual) { + ret = sst_byte_write(nor, to, buf, retlen); + if (ret) + goto done; + } + to += actual; + + ret = write_enable(nor->dev); + if (ret) + goto done; + + for (; actual < len - 1; actual += 2) { + nor->program_opcode = SNOR_OP_AAI_WP; + + ret = ops->write(nor->dev, to, 2, buf + actual); + if (ret) { + debug("spi-nor: sst word program failed\n"); + break; + } + + ret = spi_nor_wait_till_ready(nor->dev, SNOR_READY_WAIT_PROG); + if (ret) + break; + + to += 2; + *retlen += 2; + } + + if (!ret) + ret = write_disable(nor->dev); + + /* If there is a single trailing byte, write it out */ + if (!ret && actual != len) + ret = sst_byte_write(nor, to, buf + actual, retlen); + + done: + return ret; +} + +static int sst_mwrite_bp(struct udevice *dev, loff_t to, size_t len, + size_t *retlen, const u_char *buf) +{ + struct mtd_info *mtd = mtd_get_info(dev); + int devnum = mtd->devnum; + struct spi_nor *nor; + size_t actual; + int ret; + + nor = find_spi_nor_device(devnum); + if (!nor) + return -ENODEV; + + for (actual = 0; actual < len; actual++) { + ret = sst_byte_write(nor, to, buf + actual, retlen); + if (ret) { + debug("spi-nor: sst byte program failed\n"); + break; + } + to++; + } + + if (!ret) + ret = write_disable(nor->dev); + + return ret; +} +#endif + #ifdef CONFIG_SPI_NOR_MACRONIX static int macronix_quad_enable(struct udevice *dev) { @@ -482,6 +589,14 @@ int spi_nor_scan(struct spi_nor *nor) nor->flags |= SNOR_F_SST_WRITE; ops->write = spi_nor_mwrite; +#if defined(CONFIG_SPI_NOR_SST) + if (nor->flags & SNOR_F_SST_WRITE) { + if (nor->mode & SNOR_WRITE_1_1_BYTE) + ops->write = sst_mwrite_bp; + else + ops->write = sst_mwrite_wp; + } +#endif /* compute the flash size */ nor->page_size = info->page_size; -- 2.7.4 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot