spi: cadence-qspi: add early busywait to cqspi_wait_for_bit()
authorThéo Lebrun <theo.lebrun@bootlin.com>
Tue, 23 Apr 2024 10:01:42 +0000 (12:01 +0200)
committerMark Brown <broonie@kernel.org>
Fri, 26 Apr 2024 02:09:24 +0000 (11:09 +0900)
Call readl_relaxed_poll_timeout() with no sleep at the start of
cqspi_wait_for_bit(). If its short timeout expires, a sleeping
readl_relaxed_poll_timeout() call takes the relay.

The reason is to avoid hrtimer interrupts on the system. All read
operations are expected to take less than 100µs.

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

index a82e23526a6f0d608970fb5efbbf4481b454bbda..87c88ee708e402a5c7a81e69c93ae3992eb8565c 100644 (file)
@@ -120,6 +120,7 @@ struct cqspi_driver_platdata {
 /* Operation timeout value */
 #define CQSPI_TIMEOUT_MS                       500
 #define CQSPI_READ_TIMEOUT_MS                  10
+#define CQSPI_BUSYWAIT_TIMEOUT_US              500
 
 /* Runtime_pm autosuspend delay */
 #define CQSPI_AUTOSUSPEND_TIMEOUT              2000
@@ -298,13 +299,27 @@ struct cqspi_driver_platdata {
 
 #define CQSPI_REG_VERSAL_DMA_VAL               0x602
 
-static int cqspi_wait_for_bit(void __iomem *reg, const u32 mask, bool clr)
+static int cqspi_wait_for_bit(const struct cqspi_driver_platdata *ddata,
+                             void __iomem *reg, const u32 mask, bool clr,
+                             bool busywait)
 {
+       u64 timeout_us = CQSPI_TIMEOUT_MS * USEC_PER_MSEC;
        u32 val;
 
+       if (busywait) {
+               int ret = readl_relaxed_poll_timeout(reg, val,
+                                                    (((clr ? ~val : val) & mask) == mask),
+                                                    0, CQSPI_BUSYWAIT_TIMEOUT_US);
+
+               if (ret != -ETIMEDOUT)
+                       return ret;
+
+               timeout_us -= CQSPI_BUSYWAIT_TIMEOUT_US;
+       }
+
        return readl_relaxed_poll_timeout(reg, val,
                                          (((clr ? ~val : val) & mask) == mask),
-                                         10, CQSPI_TIMEOUT_MS * 1000);
+                                         10, timeout_us);
 }
 
 static bool cqspi_is_idle(struct cqspi_st *cqspi)
@@ -434,8 +449,8 @@ static int cqspi_exec_flash_cmd(struct cqspi_st *cqspi, unsigned int reg)
        writel(reg, reg_base + CQSPI_REG_CMDCTRL);
 
        /* Polling for completion. */
-       ret = cqspi_wait_for_bit(reg_base + CQSPI_REG_CMDCTRL,
-                                CQSPI_REG_CMDCTRL_INPROGRESS_MASK, 1);
+       ret = cqspi_wait_for_bit(cqspi->ddata, reg_base + CQSPI_REG_CMDCTRL,
+                                CQSPI_REG_CMDCTRL_INPROGRESS_MASK, 1, true);
        if (ret) {
                dev_err(&cqspi->pdev->dev,
                        "Flash command execution timed out.\n");
@@ -790,8 +805,8 @@ static int cqspi_indirect_read_execute(struct cqspi_flash_pdata *f_pdata,
        }
 
        /* Check indirect done status */
-       ret = cqspi_wait_for_bit(reg_base + CQSPI_REG_INDIRECTRD,
-                                CQSPI_REG_INDIRECTRD_DONE_MASK, 0);
+       ret = cqspi_wait_for_bit(cqspi->ddata, reg_base + CQSPI_REG_INDIRECTRD,
+                                CQSPI_REG_INDIRECTRD_DONE_MASK, 0, true);
        if (ret) {
                dev_err(dev, "Indirect read completion error (%i)\n", ret);
                goto failrd;
@@ -1091,8 +1106,8 @@ static int cqspi_indirect_write_execute(struct cqspi_flash_pdata *f_pdata,
        }
 
        /* Check indirect done status */
-       ret = cqspi_wait_for_bit(reg_base + CQSPI_REG_INDIRECTWR,
-                                CQSPI_REG_INDIRECTWR_DONE_MASK, 0);
+       ret = cqspi_wait_for_bit(cqspi->ddata, reg_base + CQSPI_REG_INDIRECTWR,
+                                CQSPI_REG_INDIRECTWR_DONE_MASK, 0, false);
        if (ret) {
                dev_err(dev, "Indirect write completion error (%i)\n", ret);
                goto failwr;