This is an automated email from the ASF dual-hosted git repository.

xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new aeab6fbf989 spi: let a sequence keep the chip select asserted
aeab6fbf989 is described below

commit aeab6fbf9890fc1f17253d086760645a434d668a
Author: p-szafonimateusz <[email protected]>
AuthorDate: Tue Jul 14 15:12:40 2026 +0200

    spi: let a sequence keep the chip select asserted
    
    spi_transfer() always de-selects the device at the end of a sequence, so
    a caller cannot express "keep CS asserted for the next sequence". A
    protocol backend needs that: virtio-spi carries a cs_change flag whose
    false value means the next request continues on the same chip select.
    
    Add spi_sequence_s.keepcs. When it is set the trailing SPI_SELECT() is
    skipped; an aborted sequence (ret < 0) still de-selects, so CS is never
    left asserted after an error. Honor HWFEAT_FORCE_CS_ACTIVE/INACTIVE_AFTER_
    TRANSFER in the per-transfer de-select decision as well.
    
    Signed-off-by: p-szafonimateusz <[email protected]>
---
 drivers/spi/spi_transfer.c       | 27 +++++++++++++++++++++++++--
 include/nuttx/spi/spi_transfer.h |  1 +
 2 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/spi_transfer.c b/drivers/spi/spi_transfer.c
index cb38c37abee..c26e3d5f5a6 100644
--- a/drivers/spi/spi_transfer.c
+++ b/drivers/spi/spi_transfer.c
@@ -95,6 +95,8 @@ int spi_transfer(FAR struct spi_dev_s *spi, FAR struct 
spi_sequence_s *seq)
 
   for (i = 0, trans = seq->trans; i < (int)seq->ntrans; i++, trans++)
     {
+      bool deselect = trans->deselect;
+
       /* Establish the fixed SPI attributes for unique to this transaction */
 
 #ifdef CONFIG_SPI_HWFEATURES
@@ -104,6 +106,19 @@ int spi_transfer(FAR struct spi_dev_s *spi, FAR struct 
spi_sequence_s *seq)
           spierr("ERROR: SPI_HWFEATURES failed: %d\n", ret);
           break;
         }
+
+#  ifdef CONFIG_SPI_CS_CONTROL
+      /* The CS forcing features override the per-transfer deselect */
+
+      if ((trans->hwfeat & HWFEAT_FORCE_CS_INACTIVE_AFTER_TRANSFER) != 0)
+        {
+          deselect = true;
+        }
+      else if ((trans->hwfeat & HWFEAT_FORCE_CS_ACTIVE_AFTER_TRANSFER) != 0)
+        {
+          deselect = false;
+        }
+#  endif
 #endif
 
 #ifdef CONFIG_SPI_CMDDATA
@@ -125,7 +140,7 @@ int spi_transfer(FAR struct spi_dev_s *spi, FAR struct 
spi_sequence_s *seq)
 
       /* Possibly de-select the SPI device after the transfer */
 
-      if (trans->deselect)
+      if (deselect)
         {
           SPI_SELECT(spi, seq->dev, false);
         }
@@ -138,7 +153,15 @@ int spi_transfer(FAR struct spi_dev_s *spi, FAR struct 
spi_sequence_s *seq)
         }
     }
 
-  SPI_SELECT(spi, seq->dev, false);
+  /* De-select unless the sequence keeps CS asserted for a follow-up
+   * sequence; an aborted sequence always de-selects.
+   */
+
+  if (!seq->keepcs || ret < 0)
+    {
+      SPI_SELECT(spi, seq->dev, false);
+    }
+
   SPI_LOCK(spi, false);
   return ret;
 }
diff --git a/include/nuttx/spi/spi_transfer.h b/include/nuttx/spi/spi_transfer.h
index 8ec086ca45a..e0fd87e14ee 100644
--- a/include/nuttx/spi/spi_transfer.h
+++ b/include/nuttx/spi/spi_transfer.h
@@ -101,6 +101,7 @@ struct spi_sequence_s
   uint8_t mode;                /* See enum spi_mode_e */
   uint8_t nbits;               /* Number of bits */
   uint8_t ntrans;              /* Number of transactions */
+  uint8_t keepcs;              /* Keep CS asserted after the sequence */
   uint32_t frequency;          /* SPI frequency (Hz) */
 #ifdef CONFIG_SPI_DELAY_CONTROL
   uint32_t a;                  /* Arguments to setdelay() */

Reply via email to