| From 61eca955154dfe5876882ca6281fa199eb094876 Mon Sep 17 00:00:00 2001 |
| From: Vladimir Oltean <olteanv@gmail.com> |
| Date: Sat, 28 Dec 2019 15:55:36 +0200 |
| Subject: [PATCH] spi: spi-fsl-dspi: Fix 16-bit word order in 32-bit XSPI mode |
| |
| commit ca59d5a51690d5b9340343dc36792a252e9414ae upstream. |
| |
| When used in Extended SPI mode on LS1021A, the DSPI controller wants to |
| have the least significant 16-bit word written first to the TX FIFO. |
| |
| In fact, the LS1021A reference manual says: |
| |
| 33.5.2.4.2 Draining the TX FIFO |
| |
| When Extended SPI Mode (DSPIx_MCR[XSPI]) is enabled, if the frame size |
| of SPI Data to be transmitted is more than 16 bits, then it causes two |
| Data entries to be popped from TX FIFO simultaneously which are |
| transferred to the shift register. The first of the two popped entries |
| forms the 16 least significant bits of the SPI frame to be transmitted. |
| |
| So given the following TX buffer: |
| |
| +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+ |
| | 0x0 | 0x1 | 0x2 | 0x3 | 0x4 | 0x5 | 0x6 | 0x7 | 0x8 | 0x9 | 0xa | 0xb | |
| +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+ |
| | 32-bit word 1 | 32-bit word 2 | 32-bit word 3 | |
| +-----------------------+-----------------------+-----------------------+ |
| |
| The correct way that a little-endian system should transmit it on the |
| wire when bits_per_word is 32 is: |
| |
| 0x03020100 |
| 0x07060504 |
| 0x0b0a0908 |
| |
| But it is actually transmitted as following, as seen with a scope: |
| |
| 0x01000302 |
| 0x05040706 |
| 0x09080b0a |
| |
| It appears that this patch has been submitted at least once before: |
| https://lkml.org/lkml/2018/9/21/286 |
| but in that case Chuanhua Han did not manage to explain the problem |
| clearly enough and the patch did not get merged, leaving XSPI mode |
| broken. |
| |
| Fixes: 8fcd151d2619 ("spi: spi-fsl-dspi: XSPI FIFO handling (in TCFQ mode)") |
| Cc: Esben Haabendal <eha@deif.com> |
| Cc: Chuanhua Han <chuanhua.han@nxp.com> |
| Signed-off-by: Vladimir Oltean <olteanv@gmail.com> |
| Link: https://lore.kernel.org/r/20191228135536.14284-1-olteanv@gmail.com |
| Signed-off-by: Mark Brown <broonie@kernel.org> |
| Cc: stable@vger.kernel.org |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c |
| index 545fc8189fb0..b5f60a97a2d2 100644 |
| --- a/drivers/spi/spi-fsl-dspi.c |
| +++ b/drivers/spi/spi-fsl-dspi.c |
| @@ -596,21 +596,14 @@ static void dspi_tcfq_write(struct fsl_dspi *dspi) |
| dspi->tx_cmd |= SPI_PUSHR_CMD_CTCNT; |
| |
| if (dspi->devtype_data->xspi_mode && dspi->bits_per_word > 16) { |
| - /* Write two TX FIFO entries first, and then the corresponding |
| - * CMD FIFO entry. |
| + /* Write the CMD FIFO entry first, and then the two |
| + * corresponding TX FIFO entries. |
| */ |
| u32 data = dspi_pop_tx(dspi); |
| |
| - if (dspi->cur_chip->ctar_val & SPI_CTAR_LSBFE(1)) { |
| - /* LSB */ |
| - tx_fifo_write(dspi, data & 0xFFFF); |
| - tx_fifo_write(dspi, data >> 16); |
| - } else { |
| - /* MSB */ |
| - tx_fifo_write(dspi, data >> 16); |
| - tx_fifo_write(dspi, data & 0xFFFF); |
| - } |
| cmd_fifo_write(dspi); |
| + tx_fifo_write(dspi, data & 0xFFFF); |
| + tx_fifo_write(dspi, data >> 16); |
| } else { |
| /* Write one entry to both TX FIFO and CMD FIFO |
| * simultaneously. |
| -- |
| 2.7.4 |
| |