From 862dd2a946aa1417f013fb748e2aa0f4349b405b Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Fri, 27 Dec 2019 03:24:17 +0200 Subject: spi: Don't look at TX buffer for PTP system timestamping The API for PTP system timestamping (associating a SPI transaction with the system time at which it was transferred) is flawed: it assumes that the xfer->tx_buf pointer will always be present. This is, of course, not always the case. So introduce a "progress" variable that denotes how many word have been transferred. Fix the Freescale DSPI driver, the only user of the API so far, in the same patch. Fixes: b42faeee718c ("spi: Add a PTP system timestamp to the transfer structure") Fixes: d6b71dfaeeba ("spi: spi-fsl-dspi: Implement the PTP system timestamping for TCFQ mode") Signed-off-by: Vladimir Oltean Link: https://lore.kernel.org/r/20191227012417.1057-1-olteanv@gmail.com Signed-off-by: Mark Brown --- drivers/spi/spi-fsl-dspi.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers/spi/spi-fsl-dspi.c') diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index 442cff71a0d2..9c3934efe2b1 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -185,6 +185,7 @@ struct fsl_dspi { struct spi_transfer *cur_transfer; struct spi_message *cur_msg; struct chip_data *cur_chip; + size_t progress; size_t len; const void *tx; void *rx; @@ -658,7 +659,7 @@ static int dspi_rxtx(struct fsl_dspi *dspi) u32 spi_tcr; spi_take_timestamp_post(dspi->ctlr, dspi->cur_transfer, - dspi->tx - dspi->bytes_per_word, !dspi->irq); + dspi->progress, !dspi->irq); /* Get transfer counter (in number of SPI transfers). It was * reset to 0 when transfer(s) were started. @@ -667,6 +668,7 @@ static int dspi_rxtx(struct fsl_dspi *dspi) spi_tcnt = SPI_TCR_GET_TCNT(spi_tcr); /* Update total number of bytes that were transferred */ msg->actual_length += spi_tcnt * dspi->bytes_per_word; + dspi->progress += spi_tcnt; trans_mode = dspi->devtype_data->trans_mode; if (trans_mode == DSPI_EOQ_MODE) @@ -679,7 +681,7 @@ static int dspi_rxtx(struct fsl_dspi *dspi) return 0; spi_take_timestamp_pre(dspi->ctlr, dspi->cur_transfer, - dspi->tx, !dspi->irq); + dspi->progress, !dspi->irq); if (trans_mode == DSPI_EOQ_MODE) dspi_eoq_write(dspi); @@ -768,6 +770,7 @@ static int dspi_transfer_one_message(struct spi_controller *ctlr, dspi->rx = transfer->rx_buf; dspi->rx_end = dspi->rx + transfer->len; dspi->len = transfer->len; + dspi->progress = 0; /* Validated transfer specific frame size (defaults applied) */ dspi->bits_per_word = transfer->bits_per_word; if (transfer->bits_per_word <= 8) @@ -789,7 +792,7 @@ static int dspi_transfer_one_message(struct spi_controller *ctlr, SPI_CTARE_DTCP(1)); spi_take_timestamp_pre(dspi->ctlr, dspi->cur_transfer, - dspi->tx, !dspi->irq); + dspi->progress, !dspi->irq); trans_mode = dspi->devtype_data->trans_mode; switch (trans_mode) { -- cgit v1.2.3 From ca59d5a51690d5b9340343dc36792a252e9414ae Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Sat, 28 Dec 2019 15:55:36 +0200 Subject: spi: spi-fsl-dspi: Fix 16-bit word order in 32-bit XSPI mode 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 Cc: Chuanhua Han Signed-off-by: Vladimir Oltean Link: https://lore.kernel.org/r/20191228135536.14284-1-olteanv@gmail.com Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- drivers/spi/spi-fsl-dspi.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) (limited to 'drivers/spi/spi-fsl-dspi.c') diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index 9c3934efe2b1..8428b69c858b 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -587,21 +587,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) { - /* 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. -- cgit v1.2.3