On Tue, Jan 12, 2021 at 6:46 PM Peter Maydell <peter.mayd...@linaro.org> wrote: > > On Sun, 10 Jan 2021 at 08:15, Bin Meng <bmeng...@gmail.com> wrote: > > > > From: Bin Meng <bin.m...@windriver.com> > > > > The endianness of data exchange between tx and rx fifo is incorrect. > > Earlier bytes are supposed to show up on MSB and later bytes on LSB, > > ie: in big endian. The manual does not explicitly say this, but the > > U-Boot and Linux driver codes have a swap on the data transferred > > to tx fifo and from rx fifo. > > > > With this change, U-Boot read from / write to SPI flash tests pass. > > > > => sf test 1ff000 1000 > > SPI flash test: > > 0 erase: 0 ticks, 4096000 KiB/s 32768.000 Mbps > > 1 check: 3 ticks, 1333 KiB/s 10.664 Mbps > > 2 write: 235 ticks, 17 KiB/s 0.136 Mbps > > 3 read: 2 ticks, 2000 KiB/s 16.000 Mbps > > Test passed > > 0 erase: 0 ticks, 4096000 KiB/s 32768.000 Mbps > > 1 check: 3 ticks, 1333 KiB/s 10.664 Mbps > > 2 write: 235 ticks, 17 KiB/s 0.136 Mbps > > 3 read: 2 ticks, 2000 KiB/s 16.000 Mbps > > > > Fixes: c906a3a01582 ("i.MX: Add the Freescale SPI Controller") > > Signed-off-by: Bin Meng <bin.m...@windriver.com> > > > > --- > > > > (no changes since v3) > > > > Changes in v3: > > - Simplify the tx fifo endianness handling > > > > hw/ssi/imx_spi.c | 7 ++----- > > 1 file changed, 2 insertions(+), 5 deletions(-) > > > > diff --git a/hw/ssi/imx_spi.c b/hw/ssi/imx_spi.c > > index 47c8a0f572..b5124a6426 100644 > > --- a/hw/ssi/imx_spi.c > > +++ b/hw/ssi/imx_spi.c > > @@ -171,7 +171,6 @@ static void imx_spi_flush_txfifo(IMXSPIState *s) > > > > while (!fifo32_is_empty(&s->tx_fifo)) { > > int tx_burst = 0; > > - int index = 0; > > > > if (s->burst_length <= 0) { > > s->burst_length = imx_spi_burst_length(s); > > @@ -192,7 +191,7 @@ static void imx_spi_flush_txfifo(IMXSPIState *s) > > rx = 0; > > > > while (tx_burst > 0) { > > - uint8_t byte = tx & 0xff; > > + uint8_t byte = tx >> (tx_burst - 8); > > > > DPRINTF("writing 0x%02x\n", (uint32_t)byte); > > > > @@ -201,13 +200,11 @@ static void imx_spi_flush_txfifo(IMXSPIState *s) > > > > DPRINTF("0x%02x read\n", (uint32_t)byte); > > > > - tx = tx >> 8; > > - rx |= (byte << (index * 8)); > > + rx = (rx << 8) | byte; > > > > /* Remove 8 bits from the actual burst */ > > tx_burst -= 8; > > s->burst_length -= 8; > > - index++; > > } > > This version of the loop definitely looks a lot neater. However, > looking at the code I don't think there's anything that forces the > guest to set a burst length that's a multiple of 8, so you need > to handle that somehow. Otherwise on the last time through the > loop (tx_burst - 8) can be negative, which is undefined behaviour > when you try to shift by it.
Yes, that's why I added a patch to log the unimplemented behavior to notify the user. > I think just rounding tx_burst up to a multiple of 8 before > the start of the loop would do the right thing ? Probably. Given all flash transfers are normally multiple of 8-bits I am not sure what the real hardware behavior is when it is not multiple of 8, but I will try to add something in the next version. Regards, Bin