spi: cadence-quadspi: Fix check condition for DTR ops
authorApurva Nandan <a-nandan@ti.com>
Fri, 16 Jul 2021 23:25:03 +0000 (23:25 +0000)
committerMark Brown <broonie@kernel.org>
Thu, 5 Aug 2021 19:18:10 +0000 (20:18 +0100)
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() and suppports_mem_op() 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-nandan@ti.com>
Link: https://lore.kernel.org/r/20210716232504.182-3-a-nandan@ti.com
Signed-off-by: Mark Brown <broonie@kernel.org>
drivers/spi/spi-cadence-quadspi.c

index a2de235..101cc71 100644 (file)
@@ -325,7 +325,15 @@ static int cqspi_set_protocol(struct cqspi_flash_pdata *f_pdata,
        f_pdata->inst_width = CQSPI_INST_TYPE_SINGLE;
        f_pdata->addr_width = CQSPI_INST_TYPE_SINGLE;
        f_pdata->data_width = CQSPI_INST_TYPE_SINGLE;
-       f_pdata->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.
+        */
+       f_pdata->dtr = op->cmd.dtr &&
+                      (!op->addr.nbytes || op->addr.dtr) &&
+                      (!op->data.nbytes || op->data.dtr);
 
        switch (op->data.buswidth) {
        case 0:
@@ -1228,8 +1236,15 @@ static bool cqspi_supports_mem_op(struct spi_mem *mem,
 {
        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;