From: Quanyang Wang <quanyang.w...@windriver.com>

When reading from mt25qu512a on zcu102 board, it will return wrong data.

There are two problems:

1. The gqspi controller has a functionality to send dummy clock circles.
When write data with the fields [receive, transmit, data_xfer] = [0,0,1]
to the Generic FIFO, the controller will transmit dummy circles.
Writing common data as dummy circles will result in data corruption.

2. The flash mt25qu512a support SNOR_PROTO_1_1_4, which means that the
command and address will be sent in DQ0 and data in DQ[0:3]. In function
spi_nor_spimem_read_data, op.dummy.buswidth is assigned to op.addr.buswidth
which is 1. This results that the controller sends dummy circles in SPI
mode. But Zynq UltraScale+ Device TRM P683 suggests that Quad I/O Read
should send dummy circles in Quad SPI mode.

Make modifications that sending dummy circles by using the controller's
internal functionality in Quad SPI mode to fix the two problems above.

Signed-off-by: Quanyang Wang <quanyang.w...@windriver.com>
---
 drivers/spi/spi-zynqmp-gqspi.c | 40 +++++++++++++++-------------------
 1 file changed, 18 insertions(+), 22 deletions(-)

diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c
index c8fa6ee18ae7..6dfaf968be5c 100644
--- a/drivers/spi/spi-zynqmp-gqspi.c
+++ b/drivers/spi/spi-zynqmp-gqspi.c
@@ -520,7 +520,7 @@ static void zynqmp_qspi_filltxfifo(struct zynqmp_qspi 
*xqspi, int size)
 {
        u32 count = 0, intermediate;
 
-       while ((xqspi->bytes_to_transfer > 0) && (count < size)) {
+       while ((xqspi->bytes_to_transfer > 0) && (count < size) && 
(xqspi->txbuf)) {
                memcpy(&intermediate, xqspi->txbuf, 4);
                zynqmp_gqspi_write(xqspi, GQSPI_TXD_OFST, intermediate);
 
@@ -579,7 +579,7 @@ static void zynqmp_qspi_fillgenfifo(struct zynqmp_qspi 
*xqspi, u8 nbits,
                genfifoentry |= GQSPI_GENFIFO_DATA_XFER;
                genfifoentry |= GQSPI_GENFIFO_TX;
                transfer_len = xqspi->bytes_to_transfer;
-       } else {
+       } else if (xqspi->rxbuf) {
                genfifoentry &= ~GQSPI_GENFIFO_TX;
                genfifoentry |= GQSPI_GENFIFO_DATA_XFER;
                genfifoentry |= GQSPI_GENFIFO_RX;
@@ -587,6 +587,10 @@ static void zynqmp_qspi_fillgenfifo(struct zynqmp_qspi 
*xqspi, u8 nbits,
                        transfer_len = xqspi->dma_rx_bytes;
                else
                        transfer_len = xqspi->bytes_to_receive;
+       } else {
+               genfifoentry &= ~(GQSPI_GENFIFO_TX | GQSPI_GENFIFO_RX);
+               genfifoentry |= GQSPI_GENFIFO_DATA_XFER;
+               transfer_len = xqspi->bytes_to_transfer;
        }
        genfifoentry |= zynqmp_qspi_selectspimode(xqspi, nbits);
        xqspi->genfifoentry = genfifoentry;
@@ -1009,32 +1013,24 @@ static int zynqmp_qspi_exec_op(struct spi_mem *mem,
        }
 
        if (op->dummy.nbytes) {
-               tmpbuf = kzalloc(op->dummy.nbytes, GFP_KERNEL | GFP_DMA);
-               if (!tmpbuf)
-                       return -ENOMEM;
-               memset(tmpbuf, 0xff, op->dummy.nbytes);
-               reinit_completion(&xqspi->data_completion);
-               xqspi->txbuf = tmpbuf;
+               xqspi->txbuf = NULL;
                xqspi->rxbuf = NULL;
-               xqspi->bytes_to_transfer = op->dummy.nbytes;
+               /*
+                * xqspi->bytes_to_transfer here represents the dummy circles
+                * per data line.
+                */
+               xqspi->bytes_to_transfer = op->dummy.nbytes * 8 / 
op->dummy.buswidth;
                xqspi->bytes_to_receive = 0;
-               zynqmp_qspi_write_op(xqspi, op->dummy.buswidth,
+               /*
+                * Using op->data.buswidth instead of op->dummy.buswidth since
+                * the specification requires that the dummy.buswidth should
+                * be the same as data.buswidth.
+                */
+               zynqmp_qspi_write_op(xqspi, op->data.buswidth,
                                     genfifoentry);
                zynqmp_gqspi_write(xqspi, GQSPI_CONFIG_OFST,
                                   zynqmp_gqspi_read(xqspi, GQSPI_CONFIG_OFST) |
                                   GQSPI_CFG_START_GEN_FIFO_MASK);
-               zynqmp_gqspi_write(xqspi, GQSPI_IER_OFST,
-                                  GQSPI_IER_TXEMPTY_MASK |
-                                  GQSPI_IER_GENFIFOEMPTY_MASK |
-                                  GQSPI_IER_TXNOT_FULL_MASK);
-               if (!wait_for_completion_interruptible_timeout
-                   (&xqspi->data_completion, msecs_to_jiffies(1000))) {
-                       err = -ETIMEDOUT;
-                       kfree(tmpbuf);
-                       goto return_err;
-               }
-
-               kfree(tmpbuf);
        }
 
        if (op->data.nbytes) {
-- 
2.17.1

-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.
View/Reply Online (#9186): 
https://lists.yoctoproject.org/g/linux-yocto/message/9186
Mute This Topic: https://lists.yoctoproject.org/mt/78526814/21656
Group Owner: linux-yocto+ow...@lists.yoctoproject.org
Unsubscribe: https://lists.yoctoproject.org/g/linux-yocto/unsub 
[arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to