From: Apurva Nandan <a-nan...@ti.com>

buswidth and dtr fields in spi_mem_op are only valid when the
corresponding spi_mem_op phase has a non-zero length. For example,
SPI NAND core doesn't set buswidth when using SPI_MEM_OP_NO_ADDR
phase.

Fix the dtr checks in set_protocol() to ignore empty spi_mem_op
phases, as checking for dtr field in empty phase will result in
false negatives.

Signed-off-by: Apurva Nandan <a-nan...@ti.com>
Signed-off-by: Dhruva Gole <d-g...@ti.com>
---
 drivers/spi/cadence_qspi.c     | 11 +++++++++--
 drivers/spi/cadence_qspi_apb.c | 11 ++++++++++-
 2 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/cadence_qspi.c b/drivers/spi/cadence_qspi.c
index c7f10c501320..a858a62888e4 100644
--- a/drivers/spi/cadence_qspi.c
+++ b/drivers/spi/cadence_qspi.c
@@ -362,8 +362,15 @@ static bool cadence_spi_mem_supports_op(struct spi_slave 
*slave,
 {
        bool all_true, all_false;
 
-       all_true = op->cmd.dtr && op->addr.dtr && op->dummy.dtr &&
-                  op->data.dtr;
+       /*
+        * op->dummy.dtr is required for converting nbytes into ncycles.
+        * Also, don't check the dtr field of the op phase having zero nbytes.
+        */
+       all_true = op->cmd.dtr &&
+                  (!op->addr.nbytes || op->addr.dtr) &&
+                  (!op->dummy.nbytes || op->dummy.dtr) &&
+                  (!op->data.nbytes || op->data.dtr);
+
        all_false = !op->cmd.dtr && !op->addr.dtr && !op->dummy.dtr &&
                    !op->data.dtr;
 
diff --git a/drivers/spi/cadence_qspi_apb.c b/drivers/spi/cadence_qspi_apb.c
index 21fe2e655c5f..dfcdeff80545 100644
--- a/drivers/spi/cadence_qspi_apb.c
+++ b/drivers/spi/cadence_qspi_apb.c
@@ -120,7 +120,16 @@ static int cadence_qspi_set_protocol(struct 
cadence_spi_priv *priv,
 {
        int ret;
 
-       priv->dtr = op->data.dtr && op->cmd.dtr && op->addr.dtr;
+       /*
+        * For an op to be DTR, cmd phase along with every other non-empty
+        * phase should have dtr field set to 1. If an op phase has zero
+        * nbytes, ignore its dtr field; otherwise, check its dtr field.
+        * Also, dummy checks not performed here Since supports_op()
+        * already checks that all or none of the fields are DTR.
+        */
+       priv->dtr = op->cmd.dtr &&
+                   (!op->addr.nbytes || op->addr.dtr) &&
+                   (!op->data.nbytes || op->data.dtr);
 
        ret = cadence_qspi_buswidth_to_inst_type(op->cmd.buswidth);
        if (ret < 0)
-- 
2.25.1

Reply via email to