]> git.ipfire.org Git - thirdparty/u-boot.git/commitdiff
Revert "spi: cadence-qspi: Remove cdns, is-dma property handling"
authorMichal Simek <michal.simek@amd.com>
Mon, 20 Oct 2025 13:13:42 +0000 (15:13 +0200)
committerTom Rini <trini@konsulko.com>
Mon, 20 Oct 2025 14:28:00 +0000 (08:28 -0600)
This reverts commit a040578d8270ed8788d7663808ea63ce5ffd7840.

Based on feedback other SOCs (for example Star64) are using driver in non
DMA mode which is causing issues that's why revert this patch.
cdns,is-dma should be removed differently.

Signed-off-by: Michal Simek <michal.simek@amd.com>
Reported-by: E Shattow <e@freeshell.de>
arch/arm/dts/versal-mini-ospi.dtsi
arch/arm/dts/versal-net-mini-ospi.dtsi
drivers/spi/cadence_qspi.c
drivers/spi/cadence_qspi.h
drivers/spi/cadence_qspi_apb.c

index 6991f6a51db05f81f5348995501a2478fe750e3b..eec2a08e7c70b49627e716ed6dc0efd95b45b527 100644 (file)
@@ -38,6 +38,7 @@
                num-cs = <1>;
                cdns,fifo-depth = <256>;
                cdns,fifo-width = <4>;
+               cdns,is-dma = <1>;
                cdns,trigger-address = <0xc0000000>;
                #address-cells = <1>;
                #size-cells = <0>;
index d2d5ec8e5cbf7028c9d4b1f690928b003cfcc1a0..1c94b352dc97b07f83ef8b465ccc0a271a65cd8f 100644 (file)
@@ -52,6 +52,7 @@
                num-cs = <1>;
                cdns,fifo-depth = <256>;
                cdns,fifo-width = <4>;
+               cdns,is-dma = <1>;
                cdns,is-stig-pgm = <1>;
                cdns,trigger-address = <0xc0000000>;
                #address-cells = <1>;
index 849bd930edf09f237fe1d4e34fc663638e1eb517..599596f9f087fafcb7bcd9d00f53775104340eb2 100644 (file)
@@ -210,6 +210,7 @@ static int cadence_spi_probe(struct udevice *bus)
 
        priv->regbase           = plat->regbase;
        priv->ahbbase           = plat->ahbbase;
+       priv->is_dma            = plat->is_dma;
        priv->is_decoded_cs     = plat->is_decoded_cs;
        priv->fifo_depth        = plat->fifo_depth;
        priv->fifo_width        = plat->fifo_width;
@@ -347,7 +348,10 @@ static int cadence_spi_mem_exec_op(struct spi_slave *spi,
        case CQSPI_READ:
                err = cadence_qspi_apb_read_setup(priv, op);
                if (!err) {
-                       err = cadence_qspi_apb_dma_read(priv, op);
+                       if (priv->is_dma)
+                               err = cadence_qspi_apb_dma_read(priv, op);
+                       else
+                               err = cadence_qspi_apb_read_execute(priv, op);
                }
                break;
        case CQSPI_WRITE:
@@ -408,6 +412,8 @@ static int cadence_spi_of_to_plat(struct udevice *bus)
        if (plat->ahbsize >= SZ_8M)
                priv->use_dac_mode = true;
 
+       plat->is_dma = dev_read_bool(bus, "cdns,is-dma");
+
        /* All other parameters are embedded in the child node */
        subnode = cadence_qspi_get_subnode(bus);
        if (!ofnode_valid(subnode)) {
index 10c4ad14cc058d83e8e4b64523db5524d4491f04..879e7f8dbfb8343bce58048bd0087b97ff6b0601 100644 (file)
@@ -223,6 +223,8 @@ struct cadence_spi_plat {
        u32             tchsh_ns;
        u32             tslch_ns;
        u32             quirks;
+
+       bool            is_dma;
 };
 
 struct cadence_spi_priv {
@@ -259,6 +261,7 @@ struct cadence_spi_priv {
        bool            ddr_init;
        bool            is_decoded_cs;
        bool            use_dac_mode;
+       bool            is_dma;
 
        /* Transaction protocol parameters. */
        u8              inst_width;
@@ -289,6 +292,8 @@ int cadence_qspi_apb_command_write(struct cadence_spi_priv *priv,
 
 int cadence_qspi_apb_read_setup(struct cadence_spi_priv *priv,
                                const struct spi_mem_op *op);
+int cadence_qspi_apb_read_execute(struct cadence_spi_priv *priv,
+                                 const struct spi_mem_op *op);
 int cadence_qspi_apb_write_setup(struct cadence_spi_priv *priv,
                                 const struct spi_mem_op *op);
 int cadence_qspi_apb_write_execute(struct cadence_spi_priv *priv,
index 58be017720bc4fc2f5f12892ab5bddf6ac6d951f..4696c09f754b2361c568b30778bbcbdb58c8df5b 100644 (file)
@@ -667,6 +667,125 @@ int cadence_qspi_apb_read_setup(struct cadence_spi_priv *priv,
        return 0;
 }
 
+static u32 cadence_qspi_get_rd_sram_level(struct cadence_spi_priv *priv)
+{
+       u32 reg = readl(priv->regbase + CQSPI_REG_SDRAMLEVEL);
+       reg >>= CQSPI_REG_SDRAMLEVEL_RD_LSB;
+       return reg & CQSPI_REG_SDRAMLEVEL_RD_MASK;
+}
+
+static int cadence_qspi_wait_for_data(struct cadence_spi_priv *priv)
+{
+       unsigned int timeout = 10000;
+       u32 reg;
+
+       while (timeout--) {
+               reg = cadence_qspi_get_rd_sram_level(priv);
+               if (reg)
+                       return reg;
+               udelay(1);
+       }
+
+       return -ETIMEDOUT;
+}
+
+static int
+cadence_qspi_apb_indirect_read_execute(struct cadence_spi_priv *priv,
+                                      unsigned int n_rx, u8 *rxbuf)
+{
+       unsigned int remaining = n_rx;
+       unsigned int bytes_to_read = 0;
+       int ret;
+
+       writel(n_rx, priv->regbase + CQSPI_REG_INDIRECTRDBYTES);
+
+       /* Start the indirect read transfer */
+       writel(CQSPI_REG_INDIRECTRD_START,
+              priv->regbase + CQSPI_REG_INDIRECTRD);
+
+       while (remaining > 0) {
+               ret = cadence_qspi_wait_for_data(priv);
+               if (ret < 0) {
+                       printf("Indirect write timed out (%i)\n", ret);
+                       goto failrd;
+               }
+
+               bytes_to_read = ret;
+
+               while (bytes_to_read != 0) {
+                       bytes_to_read *= priv->fifo_width;
+                       bytes_to_read = bytes_to_read > remaining ?
+                                       remaining : bytes_to_read;
+                       /*
+                        * Handle non-4-byte aligned access to avoid
+                        * data abort.
+                        */
+                       if (((uintptr_t)rxbuf % 4) || (bytes_to_read % 4))
+                               readsb(priv->ahbbase, rxbuf, bytes_to_read);
+                       else
+                               readsl(priv->ahbbase, rxbuf,
+                                      bytes_to_read >> 2);
+                       rxbuf += bytes_to_read;
+                       remaining -= bytes_to_read;
+                       bytes_to_read = cadence_qspi_get_rd_sram_level(priv);
+               }
+       }
+
+       /* Check indirect done status */
+       ret = wait_for_bit_le32(priv->regbase + CQSPI_REG_INDIRECTRD,
+                               CQSPI_REG_INDIRECTRD_DONE, 1, 10, 0);
+       if (ret) {
+               printf("Indirect read completion error (%i)\n", ret);
+               goto failrd;
+       }
+
+       /* Clear indirect completion status */
+       writel(CQSPI_REG_INDIRECTRD_DONE,
+              priv->regbase + CQSPI_REG_INDIRECTRD);
+
+       /* Check indirect done status */
+       ret = wait_for_bit_le32(priv->regbase + CQSPI_REG_INDIRECTRD,
+                               CQSPI_REG_INDIRECTRD_DONE, 0, 10, 0);
+       if (ret) {
+               printf("Indirect read clear completion error (%i)\n", ret);
+               goto failrd;
+       }
+
+       /* Wait til QSPI is idle */
+       if (!cadence_qspi_wait_idle(priv->regbase))
+               return -EIO;
+
+       return 0;
+
+failrd:
+       /* Cancel the indirect read */
+       writel(CQSPI_REG_INDIRECTRD_CANCEL,
+              priv->regbase + CQSPI_REG_INDIRECTRD);
+       return ret;
+}
+
+int cadence_qspi_apb_read_execute(struct cadence_spi_priv *priv,
+                                 const struct spi_mem_op *op)
+{
+       u64 from = op->addr.val;
+       void *buf = op->data.buf.in;
+       size_t len = op->data.nbytes;
+
+       cadence_qspi_apb_enable_linear_mode(true);
+
+       if (priv->use_dac_mode && (from + len < priv->ahbsize)) {
+               if (len < 256 ||
+                   dma_memcpy(buf, priv->ahbbase + from, len) < 0) {
+                       memcpy_fromio(buf, priv->ahbbase + from, len);
+               }
+               if (!cadence_qspi_wait_idle(priv->regbase))
+                       return -EIO;
+               return 0;
+       }
+
+       return cadence_qspi_apb_indirect_read_execute(priv, len, buf);
+}
+
 /* Opcode + Address (3/4 bytes) */
 int cadence_qspi_apb_write_setup(struct cadence_spi_priv *priv,
                                 const struct spi_mem_op *op)