mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2025-11-21 18:51:58 +01:00
mtd: spi-nor: fix page program issue when using spi-mem driver
Some SPI controllers can't write nor->page_size bytes in a single step
because their TX FIFO is too small, but when that happens we should
make sure a WRITE_EN command before each write access and READ_SR command
after each write access is issued.
We should allow nor->write() to return a size that is smaller than the
requested write size to gracefully handle this case.
Also, the spi_nor_write_data() should return the actual number of bytes
that were written during the spi_mem_exec_op() operation.
This patch is a combination of two commits backported from kernel:
commit 630d6bd8a3b4 ("mtd: spi-nor: Support controllers with limit ...")
commit 3baa8ec88c2f ("mtd: devices: m25p80: Make sure WRITE_EN is ...")
Cc: Vignesh R <vigneshr@ti.com>
Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
Acked-by: Vignesh R <vigneshr@ti.com>
Tested-by: Shyam Saini <shyam.saini@amarulasolutions.com> # microzed
Acked-by: Jagan Teki <jagan@amarulasolutions.com>
This commit is contained in:
parent
b4ee6daad7
commit
60e2bf4678
@ -116,7 +116,6 @@ static ssize_t spi_nor_write_data(struct spi_nor *nor, loff_t to, size_t len,
|
|||||||
SPI_MEM_OP_ADDR(nor->addr_width, to, 1),
|
SPI_MEM_OP_ADDR(nor->addr_width, to, 1),
|
||||||
SPI_MEM_OP_NO_DUMMY,
|
SPI_MEM_OP_NO_DUMMY,
|
||||||
SPI_MEM_OP_DATA_OUT(len, buf, 1));
|
SPI_MEM_OP_DATA_OUT(len, buf, 1));
|
||||||
size_t remaining = len;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* get transfer protocols. */
|
/* get transfer protocols. */
|
||||||
@ -127,22 +126,16 @@ static ssize_t spi_nor_write_data(struct spi_nor *nor, loff_t to, size_t len,
|
|||||||
if (nor->program_opcode == SPINOR_OP_AAI_WP && nor->sst_write_second)
|
if (nor->program_opcode == SPINOR_OP_AAI_WP && nor->sst_write_second)
|
||||||
op.addr.nbytes = 0;
|
op.addr.nbytes = 0;
|
||||||
|
|
||||||
while (remaining) {
|
ret = spi_mem_adjust_op_size(nor->spi, &op);
|
||||||
op.data.nbytes = remaining < UINT_MAX ? remaining : UINT_MAX;
|
if (ret)
|
||||||
ret = spi_mem_adjust_op_size(nor->spi, &op);
|
return ret;
|
||||||
if (ret)
|
op.data.nbytes = len < op.data.nbytes ? len : op.data.nbytes;
|
||||||
return ret;
|
|
||||||
|
|
||||||
ret = spi_mem_exec_op(nor->spi, &op);
|
ret = spi_mem_exec_op(nor->spi, &op);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
op.addr.val += op.data.nbytes;
|
return op.data.nbytes;
|
||||||
remaining -= op.data.nbytes;
|
|
||||||
op.data.buf.out += op.data.nbytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
return len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1101,10 +1094,6 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len,
|
|||||||
goto write_err;
|
goto write_err;
|
||||||
*retlen += written;
|
*retlen += written;
|
||||||
i += written;
|
i += written;
|
||||||
if (written != page_remain) {
|
|
||||||
ret = -EIO;
|
|
||||||
goto write_err;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
write_err:
|
write_err:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user