diff options
author | Ezequiel Garcia <ezequiel.garcia@free-electrons.com> | 2013-11-14 18:25:36 -0300 |
---|---|---|
committer | Brian Norris <computersforpeace@gmail.com> | 2014-01-03 11:22:17 -0800 |
commit | fa543bef72d62c14f25c6f48f5981f7ecc5402f2 (patch) | |
tree | 1d07974be591661079f80386f65e5f1a1a866324 /drivers/mtd/nand/pxa3xx_nand.c | |
parent | e7f9a6a4628d0db43970fa3d2ba57be745416927 (diff) | |
download | blackbird-op-linux-fa543bef72d62c14f25c6f48f5981f7ecc5402f2.tar.gz blackbird-op-linux-fa543bef72d62c14f25c6f48f5981f7ecc5402f2.zip |
mtd: nand: pxa3xx: Add a read/write buffers markers
In preparation to support multiple (aka chunked, aka splitted)
page I/O, this commit adds 'data_buff_pos' and 'oob_buff_pos' fields
to keep track of where the next read (or write) should be done.
This will allow multiple calls to handle_data_pio() to continue
the read (or write) operation.
Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
Tested-by: Daniel Mack <zonque@gmail.com>
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
Diffstat (limited to 'drivers/mtd/nand/pxa3xx_nand.c')
-rw-r--r-- | drivers/mtd/nand/pxa3xx_nand.c | 40 |
1 files changed, 29 insertions, 11 deletions
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 579347bc254d..c17c28594a29 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -176,6 +176,8 @@ struct pxa3xx_nand_info { unsigned int buf_start; unsigned int buf_count; unsigned int buf_size; + unsigned int data_buff_pos; + unsigned int oob_buff_pos; /* DMA information */ int drcmr_dat; @@ -334,11 +336,12 @@ static void pxa3xx_nand_set_timing(struct pxa3xx_nand_host *host, * spare and ECC configuration. * Only applicable to READ0, READOOB and PAGEPROG commands. */ -static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info) +static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info, + struct mtd_info *mtd) { int oob_enable = info->reg_ndcr & NDCR_SPARE_EN; - info->data_size = info->fifo_size; + info->data_size = mtd->writesize; if (!oob_enable) return; @@ -426,26 +429,39 @@ static void disable_int(struct pxa3xx_nand_info *info, uint32_t int_mask) static void handle_data_pio(struct pxa3xx_nand_info *info) { + unsigned int do_bytes = min(info->data_size, info->fifo_size); + switch (info->state) { case STATE_PIO_WRITING: - __raw_writesl(info->mmio_base + NDDB, info->data_buff, - DIV_ROUND_UP(info->data_size, 4)); + __raw_writesl(info->mmio_base + NDDB, + info->data_buff + info->data_buff_pos, + DIV_ROUND_UP(do_bytes, 4)); + if (info->oob_size > 0) - __raw_writesl(info->mmio_base + NDDB, info->oob_buff, - DIV_ROUND_UP(info->oob_size, 4)); + __raw_writesl(info->mmio_base + NDDB, + info->oob_buff + info->oob_buff_pos, + DIV_ROUND_UP(info->oob_size, 4)); break; case STATE_PIO_READING: - __raw_readsl(info->mmio_base + NDDB, info->data_buff, - DIV_ROUND_UP(info->data_size, 4)); + __raw_readsl(info->mmio_base + NDDB, + info->data_buff + info->data_buff_pos, + DIV_ROUND_UP(do_bytes, 4)); + if (info->oob_size > 0) - __raw_readsl(info->mmio_base + NDDB, info->oob_buff, - DIV_ROUND_UP(info->oob_size, 4)); + __raw_readsl(info->mmio_base + NDDB, + info->oob_buff + info->oob_buff_pos, + DIV_ROUND_UP(info->oob_size, 4)); break; default: dev_err(&info->pdev->dev, "%s: invalid state %d\n", __func__, info->state); BUG(); } + + /* Update buffer pointers for multi-page read/write */ + info->data_buff_pos += do_bytes; + info->oob_buff_pos += info->oob_size; + info->data_size -= do_bytes; } #ifdef ARCH_HAS_DMA @@ -612,6 +628,8 @@ static void prepare_start_command(struct pxa3xx_nand_info *info, int command) info->buf_start = 0; info->buf_count = 0; info->oob_size = 0; + info->data_buff_pos = 0; + info->oob_buff_pos = 0; info->use_ecc = 0; info->use_spare = 1; info->retcode = ERR_NONE; @@ -622,7 +640,7 @@ static void prepare_start_command(struct pxa3xx_nand_info *info, int command) case NAND_CMD_PAGEPROG: info->use_ecc = 1; case NAND_CMD_READOOB: - pxa3xx_set_datasize(info); + pxa3xx_set_datasize(info, mtd); break; case NAND_CMD_PARAM: info->use_spare = 0; |