stm32h7: spi: fix incorrect early transfer completion

rockbox-gerrit-noreply--- via rockbox-cvs <[email protected]>
Newsgroups gmane.comp.systems.archos.rockbox.cvs
Message-ID <[email protected]>
commit 006859f16b2a2b7ec9528f0fd55e04ccb036291a
Author: Aidan MacDonald <[email protected]>
Date:   Thu Jan 1 18:22:26 2026 +0000

    stm32h7: spi: fix incorrect early transfer completion
    
    The semaphore was released after all bytes were read/written
    without waiting for the EOT event, which is why the delay at
    the end of the transfer needed to be longer than expected.
    
    Change-Id: I6b48fc01cda69564c0ec8f843afd1b0c3a9c5a3c

diff --git a/firmware/target/arm/stm32/spi-stm32h7.c b/firmware/target/arm/stm32/spi-stm32h7.c
index fc4d87eafc..b7741e0182 100644
--- a/firmware/target/arm/stm32/spi-stm32h7.c
+++ b/firmware/target/arm/stm32/spi-stm32h7.c
@@ -130,6 +130,7 @@ void stm_spi_init(struct stm_spi *spi,
     spi->clock = config->clock;
     spi->mode = config->mode;
     spi->set_cs = config->set_cs;
+    spi->eot_delay_us = 1 + (1000000 / config->freq);
 
     semaphore_init(&spi->sem, 1, 0);
 
@@ -164,7 +165,6 @@ void stm_spi_init(struct stm_spi *spi,
 
     stm32_clock_enable(spi->clock);
 
-    /* TODO: allow setting MBR here */
     reg_writelf(spi->regs, SPI_CFG1,
                 MBR(mbr),
                 CRCEN(0),
@@ -225,6 +225,8 @@ int stm_spi_xfer(struct stm_spi *spi, size_t size,
     spi->rx_buf = rx_buf;
     spi->rx_size = rx_buf ? size : 0;
 
+    membarrier();
+
     stm_spi_enable(spi, hd_tx, size);
 
     semaphore_wait(&spi->sem, TIMEOUT_BLOCK);
@@ -236,10 +238,8 @@ int stm_spi_xfer(struct stm_spi *spi, size_t size,
      * For 2.22.2 we need to wait at least 1 SCK cycle before starting the
      * next transaction. For 2.22.6, waiting 1/2 SCK cycle should be enough
      * since the EOT event is raised on a clock edge.
-     *
-     * TODO: calculate this delay time. doesn't seem to match assumptions above
      */
-    udelay(5);
+    udelay(spi->eot_delay_us);
 
     stm_spi_disable(spi);
     return 0;
@@ -251,9 +251,13 @@ void stm_spi_irq_handler(struct stm_spi *spi)
     {
         uint32_t sr = reg_readl(spi->regs, SPI_SR);
 
-        if (spi->tx_size == 0 && spi->rx_size == 0)
+        if (spi->tx_size == 0 &&
+            spi->rx_size == 0 &&
+            reg_vreadf(sr, SPI_SR, EOT))
         {
             semaphore_release(&spi->sem);
+
+            reg_writelf(spi->regs, SPI_IFCR, EOTC(1));
             reg_varl(spi->regs, SPI_IER) = 0;
             return;
         }
@@ -261,6 +265,8 @@ void stm_spi_irq_handler(struct stm_spi *spi)
         if (spi->tx_size > 0 && reg_vreadf(sr, SPI_SR, TXP))
         {
             uint32_t data = stm_spi_pack(&spi->tx_buf, &spi->tx_size);
+            if (spi->tx_size == 0)
+                reg_writelf(spi->regs, SPI_IER, TXPIE(0));
 
             reg_varl(spi->regs, SPI_DR) = data;
             continue;
@@ -272,6 +278,9 @@ void stm_spi_irq_handler(struct stm_spi *spi)
             uint32_t data = reg_readl(spi->regs, SPI_DR);
 
             stm_spi_unpack(&spi->rx_buf, &spi->rx_size, data);
+            if (spi->rx_size == 0)
+                reg_writelf(spi->regs, SPI_IER, RXPIE(0));
+
             continue;
         }
 
diff --git a/firmware/target/arm/stm32/spi-stm32h7.h b/firmware/target/arm/stm32/spi-stm32h7.h
index a6b0ef11d0..f7871a3969 100644
--- a/firmware/target/arm/stm32/spi-stm32h7.h
+++ b/firmware/target/arm/stm32/spi-stm32h7.h
@@ -81,6 +81,7 @@ struct stm_spi
     enum stm_spi_mode mode;
     stm_spi_set_cs_t set_cs;
     uint32_t frame_size;
+    uint32_t eot_delay_us;
 
     const void *tx_buf;
     size_t tx_size;
-- 
rockbox-cvs mailing list
[email protected]
https://lists.haxx.se/mailman/listinfo/rockbox-cvs
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.