spi: stm32: Add SPI_READY mode to spi controller
authorClément Le Goffic <clement.legoffic@foss.st.com>
Mon, 16 Jun 2025 09:21:02 +0000 (11:21 +0200)
committerMark Brown <broonie@kernel.org>
Tue, 24 Jun 2025 15:42:58 +0000 (16:42 +0100)
The spi ready functionality is supported by our peripheral in host and
target modes on STM32MP2x SoCs.
Update our spi controller driver to allow devices to use this
functionality.

Signed-off-by: Clément Le Goffic <clement.legoffic@foss.st.com>
Link: https://patch.msgid.link/20250616-spi-upstream-v1-1-7e8593f3f75d@foss.st.com
Signed-off-by: Mark Brown <broonie@kernel.org>
drivers/spi/spi-stm32.c

index da3517d7102dce5f830cdf0dbdee3e19184f69c5..2bcd4a43676daaa7273c9de8ba0bf9c9c9f14063 100644 (file)
 /* STM32H7_SPI_I2SCFGR bit fields */
 #define STM32H7_SPI_I2SCFGR_I2SMOD     BIT(0)
 
+/* STM32MP25_SPICFG2 bit fields */
+#define STM32MP25_SPI_CFG2_RDIOM       BIT(13)
+
 /* STM32MP25 SPI registers bit fields */
 #define STM32MP25_SPI_HWCFGR1                  0x3F0
 
@@ -222,6 +225,7 @@ struct stm32_spi_reg {
  * @rx: SPI RX data register
  * @tx: SPI TX data register
  * @fullcfg: SPI full or limited feature set register
+ * @rdy_en: SPI ready feature register
  */
 struct stm32_spi_regspec {
        const struct stm32_spi_reg en;
@@ -235,6 +239,7 @@ struct stm32_spi_regspec {
        const struct stm32_spi_reg rx;
        const struct stm32_spi_reg tx;
        const struct stm32_spi_reg fullcfg;
+       const struct stm32_spi_reg rdy_en;
 };
 
 struct stm32_spi;
@@ -415,6 +420,8 @@ static const struct stm32_spi_regspec stm32mp25_spi_regspec = {
        .tx = { STM32H7_SPI_TXDR },
 
        .fullcfg = { STM32MP25_SPI_HWCFGR1, STM32MP25_SPI_HWCFGR1_FULLCFG },
+
+       .rdy_en = { STM32H7_SPI_CFG2, STM32MP25_SPI_CFG2_RDIOM },
 };
 
 static inline void stm32_spi_set_bits(struct stm32_spi *spi,
@@ -1172,15 +1179,21 @@ static int stm32_spi_prepare_msg(struct spi_controller *ctrl,
        else
                clrb |= spi->cfg->regs->cs_high.mask;
 
-       dev_dbg(spi->dev, "cpol=%d cpha=%d lsb_first=%d cs_high=%d\n",
+       if (spi_dev->mode & SPI_READY)
+               setb |= spi->cfg->regs->rdy_en.mask;
+       else
+               clrb |= spi->cfg->regs->rdy_en.mask;
+
+       dev_dbg(spi->dev, "cpol=%d cpha=%d lsb_first=%d cs_high=%d rdy=%d\n",
                !!(spi_dev->mode & SPI_CPOL),
                !!(spi_dev->mode & SPI_CPHA),
                !!(spi_dev->mode & SPI_LSB_FIRST),
-               !!(spi_dev->mode & SPI_CS_HIGH));
+               !!(spi_dev->mode & SPI_CS_HIGH),
+               !!(spi_dev->mode & SPI_READY));
 
        spin_lock_irqsave(&spi->lock, flags);
 
-       /* CPOL, CPHA and LSB FIRST bits have common register */
+       /* CPOL, CPHA, LSB FIRST, CS_HIGH and RDY_EN bits have common register */
        if (clrb || setb)
                writel_relaxed(
                        (readl_relaxed(spi->base + spi->cfg->regs->cpol.reg) &
@@ -1768,6 +1781,13 @@ static int stm32_spi_transfer_one_setup(struct stm32_spi *spi,
        spi->cur_bpw = transfer->bits_per_word;
        spi->cfg->set_bpw(spi);
 
+       if (spi_dev->mode & SPI_READY && spi->cur_bpw < 8) {
+               writel_relaxed(readl_relaxed(spi->base + spi->cfg->regs->rdy_en.reg) &
+                               ~spi->cfg->regs->rdy_en.mask,
+                                       spi->base + spi->cfg->regs->rdy_en.reg);
+               dev_dbg(spi->dev, "RDY logic disabled as bits per word < 8\n");
+       }
+
        /* Update spi->cur_speed with real clock speed */
        if (STM32_SPI_HOST_MODE(spi)) {
                mbr = stm32_spi_prepare_mbr(spi, transfer->speed_hz,
@@ -2179,7 +2199,7 @@ static int stm32_spi_probe(struct platform_device *pdev)
        ctrl->auto_runtime_pm = true;
        ctrl->bus_num = pdev->id;
        ctrl->mode_bits = SPI_CPHA | SPI_CPOL | SPI_CS_HIGH | SPI_LSB_FIRST |
-                         SPI_3WIRE;
+                         SPI_3WIRE | SPI_READY;
        ctrl->bits_per_word_mask = spi->cfg->get_bpw_mask(spi);
        ctrl->max_speed_hz = spi->clk_rate / spi->cfg->baud_rate_div_min;
        ctrl->min_speed_hz = spi->clk_rate / spi->cfg->baud_rate_div_max;