From: Apurva Nandan <[email protected]>

cadence-quadspi has a builtin Auto-HW polling funtionality
using which it keep tracks of completion of write operations.
When Auto-HW polling is enabled, it automatically initiates
status register read operation, until the flash clears its
busy bit.

However, the controller doesn't allow an address phase during
auto-polling. Unlike SPI NOR flashes, SPI NAND flashes do
require the address of status register when polling the busy
bit using the read register operation. As Auto-HW polling is
enabled by default, cadence-quadspi returns a timeout for
every write operation after an indefinite amount of polling
on SPI NAND flashes.

Add a quirk to write to the CQSPI_REG_WR_COMPLETION_CTRL register
on the controller in order to disable Auto-HW polling as the
spi-nor core, spinand core, etc. take care of polling the busy
bit on their own.

Signed-off-by: Apurva Nandan <[email protected]>
Signed-off-by: Anurag Dutta <[email protected]>
---

Hi
This patch is taken from kernel commit [1].
[1] 98d948eb8331 ("spi: cadence-quadspi: fix write completion support")

 drivers/spi/cadence_qspi.c     |  7 +++++++
 drivers/spi/cadence_qspi.h     |  1 +
 drivers/spi/cadence_qspi_apb.c | 21 ++++++++++++---------
 3 files changed, 20 insertions(+), 9 deletions(-)

diff --git a/drivers/spi/cadence_qspi.c b/drivers/spi/cadence_qspi.c
index d1404e13810..b164d6b8647 100644
--- a/drivers/spi/cadence_qspi.c
+++ b/drivers/spi/cadence_qspi.c
@@ -29,6 +29,7 @@
 /* Quirks */
 #define CQSPI_DISABLE_STIG_MODE                BIT(0)
 #define CQSPI_DMA_MODE                 BIT(1)
+#define CQSPI_NO_SUPPORT_WR_COMPLETION BIT(2)
 
 __weak int cadence_qspi_apb_dma_read(struct cadence_spi_priv *priv,
                                     const struct spi_mem_op *op)
@@ -231,6 +232,12 @@ static int cadence_spi_probe(struct udevice *bus)
                debug("Cadence QSPI: DMA mode enabled\n");
        }
 
+       /* write completion is supported by default */
+       priv->wr_completion = true;
+
+       if (priv->quirks & CQSPI_NO_SUPPORT_WR_COMPLETION)
+               priv->wr_completion = false;
+
        if (IS_ENABLED(CONFIG_ZYNQMP_FIRMWARE))
                xilinx_pm_request(PM_REQUEST_NODE, PM_DEV_OSPI,
                                  ZYNQMP_PM_CAPABILITY_ACCESS, 
ZYNQMP_PM_MAX_QOS,
diff --git a/drivers/spi/cadence_qspi.h b/drivers/spi/cadence_qspi.h
index 1e9081c2d17..2398e7a8dad 100644
--- a/drivers/spi/cadence_qspi.h
+++ b/drivers/spi/cadence_qspi.h
@@ -260,6 +260,7 @@ struct cadence_spi_priv {
        bool            is_decoded_cs;
        bool            use_dac_mode;
        bool            is_dma;
+       bool            wr_completion;
 
        /* Transaction protocol parameters. */
        u8              inst_width;
diff --git a/drivers/spi/cadence_qspi_apb.c b/drivers/spi/cadence_qspi_apb.c
index 0d4bc685f5d..e43bd1f0f75 100644
--- a/drivers/spi/cadence_qspi_apb.c
+++ b/drivers/spi/cadence_qspi_apb.c
@@ -823,15 +823,18 @@ int cadence_qspi_apb_write_setup(struct cadence_spi_priv 
*priv,
 
        writel(op->addr.val, priv->regbase + CQSPI_REG_INDIRECTWRSTARTADDR);
 
-       if (priv->dtr) {
-               /*
-                * Some flashes like the cypress Semper flash expect a 4-byte
-                * dummy address with the Read SR command in DTR mode, but this
-                * controller does not support sending address with the Read SR
-                * command. So, disable write completion polling on the
-                * controller's side. spi-nor will take care of polling the
-                * status register.
-                */
+       /*
+        * SPI NAND flashes require the address of the status register to be
+        * passed in the Read SR command. Also, some SPI NOR flashes like the
+        * cypress Semper flash expect a 4-byte dummy address in the Read SR
+        * command in DTR mode.
+        *
+        * But this controller does not support address phase in the Read SR
+        * command when doing auto-HW polling. So, disable write completion
+        * polling on the controller's side. spinand and spi-nor will take
+        * care of polling the status register.
+        */
+       if (priv->wr_completion) {
                reg = readl(priv->regbase + CQSPI_REG_WR_COMPLETION_CTRL);
                reg |= CQSPI_REG_WR_DISABLE_AUTO_POLL;
                writel(reg, priv->regbase + CQSPI_REG_WR_COMPLETION_CTRL);
-- 
2.34.1

Reply via email to