On Mon, 08/01/2018 12:18, Vignesh R wrote: > Make flash writes 32 bit aligned by using bounce buffers to deal with non 32 > bit > aligned buffers. Allocate a 512 byte bounce buffer (max known page size > currently) for this case.
Looking at drivers/mtd/spi/sf_dataflash.c, I see at least one chip with 1024 byte page size (at45db642d). This should probably be a constant somewhere, or at least be checked at runtime, see below. > This is required because as per TI K2G TRM[1], the external master is only > permitted to issue 32-bit data interface writes until the last word of an > indirect > transfer. Otherwise indirect writes is known to fail sometimes. > > [1] http://www.ti.com/lit/ug/spruhy8g/spruhy8g.pdf > > Signed-off-by: Vignesh R <vigne...@ti.com> > --- > drivers/spi/cadence_qspi.c | 13 ++++++++++++- > drivers/spi/cadence_qspi.h | 1 + > drivers/spi/cadence_qspi_apb.c | 10 +++++----- > 3 files changed, 18 insertions(+), 6 deletions(-) > > diff --git a/drivers/spi/cadence_qspi.c b/drivers/spi/cadence_qspi.c index > 991a7160bdb8..49c9b477e678 100644 > --- a/drivers/spi/cadence_qspi.c > +++ b/drivers/spi/cadence_qspi.c > @@ -158,6 +158,10 @@ static int cadence_spi_probe(struct udevice *bus) > > priv->regbase = plat->regbase; > priv->ahbbase = plat->ahbbase; > + /* Bounce buf to handle unaligned writes. 512B is max pagesize */ > + priv->bounce_buf = malloc(512); This should probably be a named constant. > + if (!priv->bounce_buf) > + return -ENOMEM; > > if (!priv->qspi_is_init) { > cadence_qspi_apb_controller_init(plat); > @@ -259,8 +263,15 @@ static int cadence_spi_xfer(struct udevice *dev, unsigned > int bitlen, > err = cadence_qspi_apb_indirect_write_setup > (plat, priv->cmd_len, cmd_buf); > if (!err) { > + const u8 *txbuf = dout; > + > + if ((uintptr_t)txbuf % 4) { > + memcpy(priv->bounce_buf, dout, > + data_bytes); Without checking the size of the buffer allocated for bounce_buf here, you risk a buffer overflow for chips with larger page size. > + txbuf = priv->bounce_buf; > + } > err = cadence_qspi_apb_indirect_write_execute > - (plat, data_bytes, dout); > + (plat, data_bytes, txbuf); > } > break; > default: > diff --git a/drivers/spi/cadence_qspi.h b/drivers/spi/cadence_qspi.h index > 83154210bd95..c97419af3de3 100644 > --- a/drivers/spi/cadence_qspi.h > +++ b/drivers/spi/cadence_qspi.h > @@ -43,6 +43,7 @@ struct cadence_spi_priv { > unsigned int qspi_calibrated_hz; > unsigned int qspi_calibrated_cs; > unsigned int previous_hz; > + void *bounce_buf; > }; > > /* Functions call declaration */ > diff --git a/drivers/spi/cadence_qspi_apb.c b/drivers/spi/cadence_qspi_apb.c > index fa8af33ae19b..fd3ece4cb129 100644 > --- a/drivers/spi/cadence_qspi_apb.c > +++ b/drivers/spi/cadence_qspi_apb.c > @@ -727,11 +727,11 @@ int cadence_qspi_apb_indirect_write_execute(struct > cadence_spi_platdata *plat, > > while (remaining > 0) { > write_bytes = remaining > page_size ? page_size : remaining; > - /* Handle non-4-byte aligned access to avoid data abort. */ > - if (((uintptr_t)txbuf % 4) || (write_bytes % 4)) > - writesb(plat->ahbbase, txbuf, write_bytes); > - else > - writesl(plat->ahbbase, txbuf, write_bytes >> 2); > + writesl(plat->ahbbase, txbuf, write_bytes >> 2); > + if (write_bytes % 4) > + writesb(plat->ahbbase, > + txbuf + rounddown(write_bytes, 4), > + write_bytes % 4); > > ret = wait_for_bit("QSPI", plat->regbase + > CQSPI_REG_SDRAMLEVEL, > CQSPI_REG_SDRAMLEVEL_WR_MASK << > -- > 2.15.1 Regards, Simon _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot