[PATCH 1/4] mtd: spi-nor-core: Do not start or end writes at odd address in DTR mode
Jon Humphreys
j-humphreys at ti.com
Mon Apr 1 19:08:57 CEST 2024
Manorit Chawdhry <m-chawdhry at ti.com> writes:
> From: Pratyush Yadav <p.yadav at ti.com>
>
> On DTR capable flashes like Micron Xcella the writes cannot start or end
> at an odd address in DTR mode. Extra 0xff bytes need to be prepended or
> appended respectively to make sure both the start and end addresses are
> even.
>
> Signed-off-by: Pratyush Yadav <p.yadav at ti.com>
> Reviewed-by: Vignesh Raghavendra <vigneshr at ti.com>
> Signed-off-by: Apurva Nandan <a-nandan at ti.com>
> Signed-off-by: Vignesh Raghavendra <vigneshr at ti.com>
> Signed-off-by: Manorit Chawdhry <m-chawdhry at ti.com>
> ---
> drivers/mtd/spi/spi-nor-core.c | 59 +++++++++++++++++++++++++++++++++++++++---
> 1 file changed, 55 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
> index f86003ca8c06..2b000151c97d 100644
> --- a/drivers/mtd/spi/spi-nor-core.c
> +++ b/drivers/mtd/spi/spi-nor-core.c
> @@ -1805,11 +1805,62 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len,
> if (ret < 0)
> return ret;
> #endif
> +
> write_enable(nor);
> - ret = nor->write(nor, addr, page_remain, buf + i);
> - if (ret < 0)
> - goto write_err;
> - written = ret;
> +
> + /*
> + * On DTR capable flashes like Micron Xcella the writes cannot
> + * start or end at an odd address in DTR mode. So we need to
> + * append or prepend extra 0xff bytes to make sure the start
> + * address and end address are even.
> + */
> + if (spi_nor_protocol_is_dtr(nor->write_proto) &&
> + ((addr | page_remain) & 1)) {
> + u_char *tmp;
> + size_t extra_bytes = 0;
> +
> + tmp = kmalloc(nor->page_size, 0);
> + if (!tmp) {
> + ret = -ENOMEM;
> + goto write_err;
> + }
> +
> + /* Prepend a 0xff byte if the start address is odd. */
> + if (addr & 1) {
> + tmp[0] = 0xff;
> + memcpy(tmp + 1, buf + i, page_remain);
> + addr--;
> + page_remain++;
> + extra_bytes++;
> + } else {
> + memcpy(tmp, buf + i, page_remain);
> + }
> +
> + /* Append a 0xff byte if the end address is odd. */
> + if ((addr + page_remain) & 1) {
> + tmp[page_remain + extra_bytes] = 0xff;
> + extra_bytes++;
> + page_remain++;
> + }
> +
> + ret = nor->write(nor, addr, page_remain, tmp);
> +
> + kfree(tmp);
> +
> + if (ret < 0)
> + goto write_err;
> +
> + /*
> + * We write extra bytes but they are not part of the
> + * original write.
> + */
> + written = ret - extra_bytes;
> + } else {
> + ret = nor->write(nor, addr, page_remain, buf + i);
> + if (ret < 0)
> + goto write_err;
> + written = ret;
> + }
>
> ret = spi_nor_wait_till_ready(nor);
> if (ret)
>
> --
> 2.43.2
Thanks for upstreaming!
Tested-by: Jonathan Humphreys <j-humphreys at ti.com>
More information about the U-Boot
mailing list