spi: cadence-qspi: allow FIFO depth detection
authorThéo Lebrun <theo.lebrun@bootlin.com>
Tue, 23 Apr 2024 10:01:40 +0000 (12:01 +0200)
committerMark Brown <broonie@kernel.org>
Fri, 26 Apr 2024 02:09:22 +0000 (11:09 +0900)
If FIFO depth DT property is provided, check it matches what hardware
reports and warn otherwise. Else, use hardware provided value.

Hardware exposes FIFO depth indirectly because
CQSPI_REG_SRAMPARTITION is partially read-only.

Move probe cqspi->ddata assignment prior to cqspi_of_get_pdata() call.

Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
Link: https://lore.kernel.org/r/20240423-cdns-qspi-mbly-v4-1-3d2a7b535ad0@bootlin.com
Signed-off-by: Mark Brown <broonie@kernel.org>
drivers/spi/spi-cadence-quadspi.c

index 9896e9fe7ffb5937a9f657d9e37ae10bbd8cb4ec..5a83940220a916ff803b22746d6a815baa120e6b 100644 (file)
@@ -1510,8 +1510,8 @@ static int cqspi_of_get_pdata(struct cqspi_st *cqspi)
        cqspi->is_decoded_cs = of_property_read_bool(np, "cdns,is-decoded-cs");
 
        if (of_property_read_u32(np, "cdns,fifo-depth", &cqspi->fifo_depth)) {
-               dev_err(dev, "couldn't determine fifo-depth\n");
-               return -ENXIO;
+               /* Zero signals FIFO depth should be runtime detected. */
+               cqspi->fifo_depth = 0;
        }
 
        if (of_property_read_u32(np, "cdns,fifo-width", &cqspi->fifo_width)) {
@@ -1541,8 +1541,6 @@ static void cqspi_controller_init(struct cqspi_st *cqspi)
 {
        u32 reg;
 
-       cqspi_controller_enable(cqspi, 0);
-
        /* Configure the remap address register, no remap */
        writel(0, cqspi->iobase + CQSPI_REG_REMAP);
 
@@ -1576,8 +1574,29 @@ static void cqspi_controller_init(struct cqspi_st *cqspi)
                reg |= CQSPI_REG_CONFIG_DMA_MASK;
                writel(reg, cqspi->iobase + CQSPI_REG_CONFIG);
        }
+}
 
-       cqspi_controller_enable(cqspi, 1);
+static void cqspi_controller_detect_fifo_depth(struct cqspi_st *cqspi)
+{
+       struct device *dev = &cqspi->pdev->dev;
+       u32 reg, fifo_depth;
+
+       /*
+        * Bits N-1:0 are writable while bits 31:N are read as zero, with 2^N
+        * the FIFO depth.
+        */
+       writel(U32_MAX, cqspi->iobase + CQSPI_REG_SRAMPARTITION);
+       reg = readl(cqspi->iobase + CQSPI_REG_SRAMPARTITION);
+       fifo_depth = reg + 1;
+
+       /* FIFO depth of zero means no value from devicetree was provided. */
+       if (cqspi->fifo_depth == 0) {
+               cqspi->fifo_depth = fifo_depth;
+               dev_dbg(dev, "using FIFO depth of %u\n", fifo_depth);
+       } else if (fifo_depth != cqspi->fifo_depth) {
+               dev_warn(dev, "detected FIFO depth (%u) different from config (%u)\n",
+                        fifo_depth, cqspi->fifo_depth);
+       }
 }
 
 static int cqspi_request_mmap_dma(struct cqspi_st *cqspi)
@@ -1730,6 +1749,7 @@ static int cqspi_probe(struct platform_device *pdev)
        cqspi->pdev = pdev;
        cqspi->host = host;
        cqspi->is_jh7110 = false;
+       cqspi->ddata = ddata = of_device_get_match_data(dev);
        platform_set_drvdata(pdev, cqspi);
 
        /* Obtain configuration from OF. */
@@ -1821,8 +1841,6 @@ static int cqspi_probe(struct platform_device *pdev)
        /* write completion is supported by default */
        cqspi->wr_completion = true;
 
-       ddata = of_device_get_match_data(dev);
-       cqspi->ddata = ddata;
        if (ddata) {
                if (ddata->quirks & CQSPI_NEEDS_WR_DELAY)
                        cqspi->wr_delay = 50 * DIV_ROUND_UP(NSEC_PER_SEC,
@@ -1864,7 +1882,10 @@ static int cqspi_probe(struct platform_device *pdev)
        }
 
        cqspi_wait_idle(cqspi);
+       cqspi_controller_enable(cqspi, 0);
+       cqspi_controller_detect_fifo_depth(cqspi);
        cqspi_controller_init(cqspi);
+       cqspi_controller_enable(cqspi, 1);
        cqspi->current_cs = -1;
        cqspi->sclk = 0;
 
@@ -1947,7 +1968,9 @@ static int cqspi_runtime_resume(struct device *dev)
 
        clk_prepare_enable(cqspi->clk);
        cqspi_wait_idle(cqspi);
+       cqspi_controller_enable(cqspi, 0);
        cqspi_controller_init(cqspi);
+       cqspi_controller_enable(cqspi, 1);
 
        cqspi->current_cs = -1;
        cqspi->sclk = 0;