[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