From c8516869c49677bb1468e0e2e351bc05b815e4ef Mon Sep 17 00:00:00 2001 From: Steffen Trumtrar Date: Fri, 3 May 2019 11:33:54 +0200 Subject: spi: Extend the core to ease integration of SPI memory controllers Sync with Linux v5.1-rc1. This is the barebox adoption of the commit commit c36ff266dc82f4ae797a6f3513c6ffa344f7f1c7 Author: Boris Brezillon Date: Thu Apr 26 18:18:14 2018 +0200 spi: Extend the core to ease integration of SPI memory controllers Some controllers are exposing high-level interfaces to access various kind of SPI memories. Unfortunately they do not fit in the current spi_controller model and usually have drivers placed in drivers/mtd/spi-nor which are only supporting SPI NORs and not SPI memories in general. This is an attempt at defining a SPI memory interface which works for all kinds of SPI memories (NORs, NANDs, SRAMs). Signed-off-by: Boris Brezillon Reviewed-by: Frieder Schrempf Tested-by: Frieder Schrempf Signed-off-by: Mark Brown Signed-off-by: Steffen Trumtrar Signed-off-by: Sascha Hauer --- drivers/mtd/spi-nor/spi-nor.c | 38 +++++++++++++++----------------------- 1 file changed, 15 insertions(+), 23 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 85b55c6982..851ac1c33e 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -784,7 +784,8 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) { struct spi_nor *nor = mtd_to_spi_nor(mtd); - u32 page_offset, page_size, i; + size_t page_offset, page_remain, i; + size_t retval; int ret; dev_dbg(nor->dev, "to 0x%08x, len %zd\n", (u32)to, len); @@ -793,32 +794,23 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len, if (ret) return ret; - write_enable(nor); - - page_offset = to & (nor->page_size - 1); - - /* do all the bytes fit onto one page? */ - if (page_offset + len <= nor->page_size) { - nor->write(nor, to, len, retlen, buf); - } else { - /* the size of data remaining on the first page */ - page_size = nor->page_size - page_offset; - nor->write(nor, to, page_size, retlen, buf); + for (i = 0; i < len; ) { + ssize_t written; - /* write everything in nor->page_size chunks */ - for (i = page_size; i < len; i += page_size) { - page_size = len - i; - if (page_size > nor->page_size) - page_size = nor->page_size; + page_offset = (to + i) & (nor->page_size - 1); + page_remain = min_t(size_t, nor->page_size - page_offset, + len - i); - ret = spi_nor_wait_till_ready(nor); - if (ret) - goto write_err; + write_enable(nor); + nor->write(nor, to + i, page_remain, &retval, buf + i); + written = retval; - write_enable(nor); + ret = spi_nor_wait_till_ready(nor); + if (ret) + goto write_err; - nor->write(nor, to + i, page_size, retlen, buf + i); - } + *retlen += written; + i += written; } ret = spi_nor_wait_till_ready(nor); -- cgit v1.2.3