Manorit Chawdhry <m-chawd...@ti.com> writes: > From: Pratyush Yadav <p.ya...@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.ya...@ti.com> > Reviewed-by: Vignesh Raghavendra <vigne...@ti.com> > Signed-off-by: Apurva Nandan <a-nan...@ti.com> > Signed-off-by: Vignesh Raghavendra <vigne...@ti.com> > Signed-off-by: Manorit Chawdhry <m-chawd...@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-humphr...@ti.com>