[PATCH 05/11] spi: cadence-qspi: add FIFO depth detection quirk

From: Théo Lebrun
Date: Fri Mar 08 2024 - 12:19:56 EST


Use hardware ability to read the FIFO depth thanks to
CQSPI_REG_SRAMPARTITION that is partially read-only. Keep current
behavior identical for existing compatibles.

Hide feature behind a flag. If unset and detected value is different
from the devicetree-provided value, warn.

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

Signed-off-by: Théo Lebrun <theo.lebrun@xxxxxxxxxxx>
---
drivers/spi/spi-cadence-quadspi.c | 38 ++++++++++++++++++++++++++++++++------
1 file changed, 32 insertions(+), 6 deletions(-)

diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c
index 02a80745fa6d..d178148788f0 100644
--- a/drivers/spi/spi-cadence-quadspi.c
+++ b/drivers/spi/spi-cadence-quadspi.c
@@ -42,6 +42,7 @@ static_assert(CQSPI_MAX_CHIPSELECT <= SPI_CS_CNT_MAX);
#define CQSPI_NO_SUPPORT_WR_COMPLETION BIT(3)
#define CQSPI_SLOW_SRAM BIT(4)
#define CQSPI_NEEDS_APB_AHB_HAZARD_WAR BIT(5)
+#define CQSPI_DETECT_FIFO_DEPTH BIT(6)

/* Capabilities */
#define CQSPI_SUPPORTS_OCTAL BIT(0)
@@ -1500,13 +1501,15 @@ static int cqspi_of_get_flash_pdata(struct platform_device *pdev,

static int cqspi_of_get_pdata(struct cqspi_st *cqspi)
{
+ const struct cqspi_driver_platdata *ddata = cqspi->ddata;
struct device *dev = &cqspi->pdev->dev;
struct device_node *np = dev->of_node;
u32 id[2];

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)) {
+ if (!(ddata && ddata->quirks & CQSPI_DETECT_FIFO_DEPTH) &&
+ of_property_read_u32(np, "cdns,fifo-depth", &cqspi->fifo_depth)) {
dev_err(dev, "couldn't determine fifo-depth\n");
return -ENXIO;
}
@@ -1538,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);

@@ -1573,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)
+{
+ const struct cqspi_driver_platdata *ddata = cqspi->ddata;
+ 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;
+
+ if (ddata && ddata->quirks & CQSPI_DETECT_FIFO_DEPTH) {
+ 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)
@@ -1728,6 +1750,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. */
@@ -1819,8 +1842,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,
@@ -1862,7 +1883,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;

@@ -1945,7 +1969,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;

--
2.44.0