From 44e2de0480a8a5a5780b6b200935a96b961b94e7 Mon Sep 17 00:00:00 2001 From: Apurva Nandan Date: Wed, 12 Apr 2023 16:28:54 +0530 Subject: [PATCH] spi: cadence-quadspi: Fix check condition for DTR ops 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 Signed-off-by: Dhruva Gole Reviewed-by: Jagan Teki --- 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 c7f10c5013..a858a62888 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 21fe2e655c..dfcdeff805 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.39.5