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

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

commit 26a5cb209474350a1790cab771d47200632daa35
Author: Gustavo Henrique Nihei <gustavo.ni...@espressif.com>
AuthorDate: Thu Apr 29 19:16:17 2021 -0300

    risc-v/esp32c3: Add support for DMA transfers on SPI driver
---
 arch/risc-v/src/esp32c3/Kconfig       |  23 ++
 arch/risc-v/src/esp32c3/esp32c3_spi.c | 411 +++++++++++++++++++++++++++++++---
 2 files changed, 405 insertions(+), 29 deletions(-)

diff --git a/arch/risc-v/src/esp32c3/Kconfig b/arch/risc-v/src/esp32c3/Kconfig
index bce1ec8..99f0213 100644
--- a/arch/risc-v/src/esp32c3/Kconfig
+++ b/arch/risc-v/src/esp32c3/Kconfig
@@ -323,6 +323,29 @@ config ESP32C3_SPI_UDCS
 
 if ESP32C3_SPI2
 
+config ESP32C3_SPI2_DMA
+       bool "SPI2 use GDMA"
+       default n
+       depends on ESP32C3_DMA
+       ---help---
+               Enable support for transfers using the GDMA engine.
+
+config ESP32C3_SPI2_DMADESC_NUM
+       int "SPI2 Master GDMA maximum number of descriptors"
+       default 2
+       depends on ESP32C3_SPI2_DMA
+       ---help---
+               Configure the maximum number of out-link/in-link descriptors to
+               be chained for a GDMA transfer.
+
+config ESP32C3_SPI2_DMATHRESHOLD
+       int "SPI2 GDMA threshold"
+       default 64
+       depends on ESP32C3_SPI2_DMA
+       ---help---
+               When SPI GDMA is enabled, GDMA transfers whose size are below 
the
+               defined threshold will be performed by polling logic.
+
 config ESP32C3_SPI2_CSPIN
        int "SPI2 CS Pin"
        default 10
diff --git a/arch/risc-v/src/esp32c3/esp32c3_spi.c 
b/arch/risc-v/src/esp32c3/esp32c3_spi.c
index d65055b..6010d25 100644
--- a/arch/risc-v/src/esp32c3/esp32c3_spi.c
+++ b/arch/risc-v/src/esp32c3/esp32c3_spi.c
@@ -32,17 +32,24 @@
 #include <stdint.h>
 #include <stdbool.h>
 #include <stdlib.h>
+#include <time.h>
 
 #include <nuttx/arch.h>
 #include <nuttx/irq.h>
+#include <nuttx/clock.h>
 #include <nuttx/semaphore.h>
 #include <nuttx/spi/spi.h>
 
 #include <arch/board/board.h>
 
 #include "esp32c3_spi.h"
+#include "esp32c3_irq.h"
 #include "esp32c3_gpio.h"
 
+#ifdef CONFIG_ESP32C3_SPI2_DMA
+#include "esp32c3_dma.h"
+#endif
+
 #include "riscv_arch.h"
 #include "hardware/esp32c3_gpio_sigmap.h"
 #include "hardware/esp32c3_pinmap.h"
@@ -62,6 +69,18 @@
 #  define SPI_HAVE_SWCS FALSE
 #endif
 
+#ifdef CONFIG_ESP32C3_SPI2_DMA
+
+/* SPI DMA RX/TX number of descriptors */
+
+#define SPI_DMA_DESC_NUM    (CONFIG_ESP32C3_SPI2_DMADESC_NUM)
+
+/* SPI DMA reset before exchange */
+
+#define SPI_DMA_RESET_MASK  (SPI_DMA_AFIFO_RST_M | SPI_RX_AFIFO_RST_M)
+
+#endif
+
 /* Verify whether SPI has been assigned IOMUX pins.
  * Otherwise, SPI signals will be routed via GPIO Matrix.
  */
@@ -119,8 +138,16 @@ struct esp32c3_spi_config_s
   uint8_t mosi_pin;           /* GPIO configuration for MOSI */
   uint8_t miso_pin;           /* GPIO configuration for MISO */
   uint8_t clk_pin;            /* GPIO configuration for CLK */
+#ifdef CONFIG_ESP32C3_SPI2_DMA
+  uint8_t periph;             /* Peripheral ID */
+  uint8_t irq;                /* Interrupt ID */
+#endif
   uint32_t clk_bit;           /* Clock enable bit */
   uint32_t rst_bit;           /* SPI reset bit */
+#ifdef CONFIG_ESP32C3_SPI2_DMA
+  uint32_t dma_clk_bit;       /* DMA clock enable bit */
+  uint32_t dma_rst_bit;       /* DMA reset bit */
+#endif
   uint32_t cs_insig;          /* SPI CS input signal index */
   uint32_t cs_outsig;         /* SPI CS output signal index */
   uint32_t mosi_insig;        /* SPI MOSI input signal index */
@@ -142,6 +169,11 @@ struct esp32c3_spi_priv_s
   const struct esp32c3_spi_config_s *config;
   int refs;             /* Reference count */
   sem_t exclsem;        /* Held while chip is selected for mutual exclusion */
+#ifdef CONFIG_ESP32C3_SPI2_DMA
+  sem_t sem_isr;        /* Interrupt wait semaphore */
+  int cpuint;           /* SPI interrupt ID */
+  int32_t dma_channel;  /* Channel assigned by the GDMA driver */
+#endif
   uint32_t frequency;   /* Requested clock frequency */
   uint32_t actual;      /* Actual clock frequency */
   enum spi_mode_e mode; /* Actual SPI hardware mode */
@@ -170,6 +202,19 @@ static uint32_t esp32c3_spi_send(FAR struct spi_dev_s 
*dev, uint32_t wd);
 static void esp32c3_spi_exchange(FAR struct spi_dev_s *dev,
                                  FAR const void *txbuffer,
                                  FAR void *rxbuffer, size_t nwords);
+#ifdef CONFIG_ESP32C3_SPI2_DMA
+static int esp32c3_spi_interrupt(int irq, void *context, FAR void *arg);
+static int esp32c3_spi_sem_waitdone(FAR struct esp32c3_spi_priv_s *priv);
+static void esp32c3_spi_dma_exchange(FAR struct esp32c3_spi_priv_s *priv,
+                                     FAR const void *txbuffer,
+                                     FAR void *rxbuffer,
+                                     uint32_t nwords);
+#else
+static void esp32c3_spi_poll_exchange(FAR struct esp32c3_spi_priv_s *priv,
+                                      FAR const void *txbuffer,
+                                      FAR void *rxbuffer,
+                                      size_t nwords);
+#endif
 #ifndef CONFIG_SPI_EXCHANGE
 static void esp32c3_spi_sndblock(FAR struct spi_dev_s *dev,
                                  FAR const void *txbuffer,
@@ -181,6 +226,9 @@ static void esp32c3_spi_recvblock(FAR struct spi_dev_s *dev,
 #ifdef CONFIG_SPI_TRIGGER
 static int esp32c3_spi_trigger(FAR struct spi_dev_s *dev);
 #endif
+#ifdef CONFIG_ESP32C3_SPI2_DMA
+static void esp32c3_spi_dma_init(FAR struct spi_dev_s *dev);
+#endif
 static void esp32c3_spi_init(FAR struct spi_dev_s *dev);
 static void esp32c3_spi_deinit(FAR struct spi_dev_s *dev);
 
@@ -198,8 +246,16 @@ static const struct esp32c3_spi_config_s 
esp32c3_spi2_config =
   .mosi_pin     = CONFIG_ESP32C3_SPI2_MOSIPIN,
   .miso_pin     = CONFIG_ESP32C3_SPI2_MISOPIN,
   .clk_pin      = CONFIG_ESP32C3_SPI2_CLKPIN,
+#ifdef CONFIG_ESP32C3_SPI2_DMA
+  .periph       = ESP32C3_PERIPH_SPI2,
+  .irq          = ESP32C3_IRQ_SPI2,
+#endif
   .clk_bit      = SYSTEM_SPI2_CLK_EN,
   .rst_bit      = SYSTEM_SPI2_RST,
+#ifdef CONFIG_ESP32C3_SPI2_DMA
+  .dma_clk_bit  = SYSTEM_SPI2_DMA_CLK_EN,
+  .dma_rst_bit  = SYSTEM_SPI2_DMA_RST,
+#endif
   .cs_insig     = FSPICS0_IN_IDX,
   .cs_outsig    = FSPICS0_OUT_IDX,
   .mosi_insig   = FSPID_IN_IDX,
@@ -243,20 +299,34 @@ static const struct spi_ops_s esp32c3_spi2_ops =
 
 static struct esp32c3_spi_priv_s esp32c3_spi2_priv =
 {
-  .spi_dev   =
-              {
-                .ops = &esp32c3_spi2_ops
-              },
-  .config    = &esp32c3_spi2_config,
-  .refs      = 0,
-  .exclsem   = SEM_INITIALIZER(0),
-  .frequency = 0,
-  .actual    = 0,
-  .mode      = 0,
-  .nbits     = 0
+  .spi_dev     =
+                {
+                  .ops = &esp32c3_spi2_ops
+                },
+  .config      = &esp32c3_spi2_config,
+  .refs        = 0,
+  .exclsem     = SEM_INITIALIZER(0),
+#ifdef CONFIG_ESP32C3_SPI2_DMA
+  .sem_isr     = SEM_INITIALIZER(0),
+  .cpuint      = -ENOMEM,
+  .dma_channel = -1,
+#endif
+  .frequency   = 0,
+  .actual      = 0,
+  .mode        = 0,
+  .nbits       = 0
 };
 #endif /* CONFIG_ESP32C3_SPI2 */
 
+#ifdef CONFIG_ESP32C3_SPI2_DMA
+
+/* SPI DMA RX/TX description */
+
+static struct esp32c3_dmadesc_s dma_rxdesc[SPI_DMA_DESC_NUM];
+static struct esp32c3_dmadesc_s dma_txdesc[SPI_DMA_DESC_NUM];
+
+#endif
+
 /****************************************************************************
  * Private Functions
  ****************************************************************************/
@@ -272,7 +342,7 @@ static struct esp32c3_spi_priv_s esp32c3_spi2_priv =
  *   bits   - Bits to be set
  *
  * Returned Value:
- *   None
+ *   None.
  *
  ****************************************************************************/
 
@@ -294,7 +364,7 @@ static inline void esp32c3_spi_set_regbits(uint32_t addr, 
uint32_t bits)
  *   bits   - Bits to be cleared
  *
  * Returned Value:
- *   None
+ *   None.
  *
  ****************************************************************************/
 
@@ -313,10 +383,10 @@ static inline void esp32c3_spi_clr_regbits(uint32_t addr, 
uint32_t bits)
  *
  * Input Parameters:
  *   dev    - Device-specific state data
- *   lock   - true: Lock spi bus, false: unlock SPI bus
+ *   lock   - true: Lock SPI bus, false: unlock SPI bus
  *
  * Returned Value:
- *   The result of lock or unlock the SPI device
+ *   The result of lock or unlock the SPI device.
  *
  ****************************************************************************/
 
@@ -338,6 +408,37 @@ static int esp32c3_spi_lock(FAR struct spi_dev_s *dev, 
bool lock)
 }
 
 /****************************************************************************
+ * Name: esp32c3_spi_sem_waitdone
+ *
+ * Description:
+ *   Wait for a transfer to complete.
+ *
+ * Input Parameters:
+ *   priv - SPI private state data
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_ESP32C3_SPI2_DMA
+static int esp32c3_spi_sem_waitdone(FAR struct esp32c3_spi_priv_s *priv)
+{
+  int ret;
+  struct timespec abstime;
+
+  clock_gettime(CLOCK_REALTIME, &abstime);
+
+  abstime.tv_sec += 10;
+  abstime.tv_nsec += 0;
+
+  ret = nxsem_timedwait_uninterruptible(&priv->sem_isr, &abstime);
+
+  return ret;
+}
+#endif
+
+/****************************************************************************
  * Name: esp32c3_spi_select
  *
  * Description:
@@ -356,7 +457,7 @@ static int esp32c3_spi_lock(FAR struct spi_dev_s *dev, bool 
lock)
  *   selected - true: slave selected, false: slave de-selected
  *
  * Returned Value:
- *   None
+ *   None.
  *
  ****************************************************************************/
 
@@ -509,7 +610,7 @@ static uint32_t esp32c3_spi_setfrequency(FAR struct 
spi_dev_s *dev,
  *   mode - The requested SPI mode
  *
  * Returned Value:
- *   none
+ *   None.
  *
  ****************************************************************************/
 
@@ -578,7 +679,7 @@ static void esp32c3_spi_setmode(FAR struct spi_dev_s *dev,
  *   nbits - The number of bits in an SPI word.
  *
  * Returned Value:
- *   none
+ *   None.
  *
  ****************************************************************************/
 
@@ -618,6 +719,115 @@ static int esp32c3_spi_hwfeatures(FAR struct spi_dev_s 
*dev,
 #endif
 
 /****************************************************************************
+ * Name: esp32c3_spi_dma_exchange
+ *
+ * Description:
+ *   Exchange a block of data from SPI by DMA.
+ *
+ * Input Parameters:
+ *   priv     - SPI private state data
+ *   txbuffer - A pointer to the buffer of data to be sent
+ *   rxbuffer - A pointer to the buffer in which to receive data
+ *   nwords   - the length of data that to be exchanged in units of words.
+ *              The wordsize is determined by the number of bits-per-word
+ *              selected for the SPI interface.  If nbits <= 8, the data is
+ *              packed into uint8_t's; if nbits >8, the data is packed into
+ *              uint16_t's
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_ESP32C3_SPI2_DMA
+static void esp32c3_spi_dma_exchange(FAR struct esp32c3_spi_priv_s *priv,
+                                     FAR const void *txbuffer,
+                                     FAR void *rxbuffer,
+                                     uint32_t nwords)
+{
+  const uint32_t total = nwords * (priv->nbits / 8);
+  const int32_t channel = priv->dma_channel;
+  uint32_t bytes = total;
+  uint32_t n;
+  uint8_t *tp;
+  uint8_t *rp;
+
+  DEBUGASSERT((txbuffer != NULL) || (rxbuffer != NULL));
+
+  spiinfo("nwords=%" PRIu32 "\n", nwords);
+
+  tp = (uint8_t *)txbuffer;
+  rp = (uint8_t *)rxbuffer;
+
+  if (tp == NULL)
+    {
+      tp = rp;
+    }
+
+  esp32c3_spi_clr_regbits(SPI_DMA_INT_RAW_REG, SPI_TRANS_DONE_INT_RAW_M);
+
+  esp32c3_spi_set_regbits(SPI_DMA_INT_ENA_REG, SPI_TRANS_DONE_INT_ENA_M);
+
+  while (bytes != 0)
+    {
+      /* Reset SPI DMA TX FIFO */
+
+      esp32c3_spi_set_regbits(SPI_DMA_CONF_REG, SPI_DMA_RESET_MASK);
+      esp32c3_spi_clr_regbits(SPI_DMA_CONF_REG, SPI_DMA_RESET_MASK);
+
+      /* Enable SPI DMA TX */
+
+      esp32c3_spi_set_regbits(SPI_DMA_CONF_REG, SPI_DMA_TX_ENA_M);
+
+      n = esp32c3_dma_setup(channel, true, dma_txdesc, SPI_DMA_DESC_NUM,
+                            tp, bytes);
+      esp32c3_dma_enable(channel, true);
+
+      putreg32((n * 8 - 1), SPI_MS_DLEN_REG);
+      esp32c3_spi_set_regbits(SPI_USER_REG, SPI_USR_MOSI_M);
+
+      tp += n;
+
+      if (rp != NULL)
+        {
+          /* Enable SPI DMA RX */
+
+          esp32c3_spi_set_regbits(SPI_DMA_CONF_REG, SPI_DMA_RX_ENA_M);
+
+          esp32c3_dma_setup(channel, false, dma_rxdesc, SPI_DMA_DESC_NUM,
+                            rp, bytes);
+          esp32c3_dma_enable(channel, false);
+
+          esp32c3_spi_set_regbits(SPI_USER_REG, SPI_USR_MISO_M);
+
+          rp += n;
+        }
+      else
+        {
+          esp32c3_spi_clr_regbits(SPI_USER_REG, SPI_USR_MISO_M);
+        }
+
+      /* Trigger start of user-defined transaction for master. */
+
+      esp32c3_spi_set_regbits(SPI_CMD_REG, SPI_UPDATE_M);
+
+      while ((getreg32(SPI_CMD_REG) & SPI_UPDATE_M) != 0)
+        {
+          ;
+        }
+
+      esp32c3_spi_set_regbits(SPI_CMD_REG, SPI_USR_M);
+
+      esp32c3_spi_sem_waitdone(priv);
+
+      bytes -= n;
+    }
+
+  esp32c3_spi_clr_regbits(SPI_DMA_INT_ENA_REG, SPI_TRANS_DONE_INT_ENA_M);
+}
+#endif
+
+/****************************************************************************
  * Name: esp32c3_spi_poll_send
  *
  * Description:
@@ -629,7 +839,7 @@ static int esp32c3_spi_hwfeatures(FAR struct spi_dev_s *dev,
  *          number of bits selected for the SPI interface.
  *
  * Returned Value:
- *   Received value
+ *   Received value.
  *
  ****************************************************************************/
 
@@ -679,7 +889,7 @@ static uint32_t esp32c3_spi_poll_send(FAR struct 
esp32c3_spi_priv_s *priv,
  *         number of bits selected for the SPI interface.
  *
  * Returned Value:
- *   Received value
+ *   Received value.
  *
  ****************************************************************************/
 
@@ -707,7 +917,7 @@ static uint32_t esp32c3_spi_send(FAR struct spi_dev_s *dev, 
uint32_t wd)
  *              uint16_t's
  *
  * Returned Value:
- *   None
+ *   None.
  *
  ****************************************************************************/
 
@@ -836,7 +1046,7 @@ static void esp32c3_spi_poll_exchange(FAR struct 
esp32c3_spi_priv_s *priv,
  *              uint16_t's
  *
  * Returned Value:
- *   None
+ *   None.
  *
  ****************************************************************************/
 
@@ -847,7 +1057,18 @@ static void esp32c3_spi_exchange(FAR struct spi_dev_s 
*dev,
 {
   FAR struct esp32c3_spi_priv_s *priv = (FAR struct esp32c3_spi_priv_s *)dev;
 
-  esp32c3_spi_poll_exchange(priv, txbuffer, rxbuffer, nwords);
+#ifdef CONFIG_ESP32C3_SPI2_DMA
+  size_t thld = CONFIG_ESP32C3_SPI2_DMATHRESHOLD;
+
+  if (nwords > thld)
+    {
+      esp32c3_spi_dma_exchange(priv, txbuffer, rxbuffer, nwords);
+    }
+  else
+#endif
+    {
+      esp32c3_spi_poll_exchange(priv, txbuffer, rxbuffer, nwords);
+    }
 }
 
 #ifndef CONFIG_SPI_EXCHANGE
@@ -868,7 +1089,7 @@ static void esp32c3_spi_exchange(FAR struct spi_dev_s *dev,
  *              packed into uint16_t's
  *
  * Returned Value:
- *   None
+ *   None.
  *
  ****************************************************************************/
 
@@ -897,7 +1118,7 @@ static void esp32c3_spi_sndblock(FAR struct spi_dev_s *dev,
  *              packed into uint16_t's
  *
  * Returned Value:
- *   None
+ *   None.
  *
  ****************************************************************************/
 
@@ -935,6 +1156,55 @@ static int esp32c3_spi_trigger(FAR struct spi_dev_s *dev)
 #endif
 
 /****************************************************************************
+ * Name: esp32c3_spi_dma_init
+ *
+ * Description:
+ *   Initialize ESP32-C3 SPI connection to GDMA engine.
+ *
+ * Input Parameters:
+ *   dev      - Device-specific state data
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_ESP32C3_SPI2_DMA
+void esp32c3_spi_dma_init(FAR struct spi_dev_s *dev)
+{
+  FAR struct esp32c3_spi_priv_s *priv = (FAR struct esp32c3_spi_priv_s *)dev;
+
+  /* Enable GDMA clock for the SPI peripheral */
+
+  modifyreg32(SYSTEM_PERIP_CLK_EN0_REG, 0, priv->config->dma_clk_bit);
+
+  /* Reset GDMA for the SPI peripheral */
+
+  modifyreg32(SYSTEM_PERIP_RST_EN0_REG, priv->config->dma_rst_bit, 0);
+
+  /* Initialize GDMA controller */
+
+  esp32c3_dma_init();
+
+  /* Request a GDMA channel for SPI peripheral */
+
+  priv->dma_channel = esp32c3_dma_request(ESP32C3_DMA_PERIPH_SPI, 1, 1,
+                                          true);
+  if (priv->dma_channel < 0)
+    {
+      spierr("Failed to allocate GDMA channel\n");
+
+      DEBUGASSERT(false);
+    }
+
+  /* Disable segment transaction mode for SPI Master */
+
+  putreg32((SPI_SLV_RX_SEG_TRANS_CLR_EN_M | SPI_SLV_TX_SEG_TRANS_CLR_EN_M),
+           SPI_DMA_CONF_REG);
+}
+#endif
+
+/****************************************************************************
  * Name: esp32c3_spi_init
  *
  * Description:
@@ -944,7 +1214,7 @@ static int esp32c3_spi_trigger(FAR struct spi_dev_s *dev)
  *   dev      - Device-specific state data
  *
  * Returned Value:
- *   None
+ *   None.
  *
  ****************************************************************************/
 
@@ -1015,6 +1285,13 @@ static void esp32c3_spi_init(FAR struct spi_dev_s *dev)
   putreg32(0, SPI_CTRL_REG);
   putreg32(VALUE_MASK(0, SPI_CS_HOLD_TIME), SPI_USER1_REG);
 
+#ifdef CONFIG_ESP32C3_SPI2_DMA
+  nxsem_init(&priv->sem_isr, 0, 0);
+  nxsem_set_protocol(&priv->sem_isr, SEM_PRIO_NONE);
+
+  esp32c3_spi_dma_init(dev);
+#endif
+
   esp32c3_spi_setfrequency(dev, config->clk_freq);
   esp32c3_spi_setbits(dev, config->width);
   esp32c3_spi_setmode(dev, config->mode);
@@ -1030,7 +1307,7 @@ static void esp32c3_spi_init(FAR struct spi_dev_s *dev)
  *   dev      - Device-specific state data
  *
  * Returned Value:
- *   None
+ *   None.
  *
  ****************************************************************************/
 
@@ -1038,6 +1315,10 @@ static void esp32c3_spi_deinit(FAR struct spi_dev_s *dev)
 {
   FAR struct esp32c3_spi_priv_s *priv = (FAR struct esp32c3_spi_priv_s *)dev;
 
+#ifdef CONFIG_ESP32C3_SPI2_DMA
+  modifyreg32(SYSTEM_PERIP_CLK_EN0_REG, priv->config->dma_clk_bit, 0);
+#endif
+
   modifyreg32(SYSTEM_PERIP_RST_EN0_REG, 0, priv->config->clk_bit);
   modifyreg32(SYSTEM_PERIP_CLK_EN0_REG, priv->config->clk_bit, 0);
 
@@ -1048,6 +1329,34 @@ static void esp32c3_spi_deinit(FAR struct spi_dev_s *dev)
 }
 
 /****************************************************************************
+ * Name: esp32c3_spi_interrupt
+ *
+ * Description:
+ *   Common SPI DMA interrupt handler.
+ *
+ * Input Parameters:
+ *   irq     - Number of the IRQ that generated the interrupt
+ *   context - Interrupt register state save info
+ *   arg     - SPI controller private data
+ *
+ * Returned Value:
+ *   Standard interrupt return value.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_ESP32C3_SPI2_DMA
+static int esp32c3_spi_interrupt(int irq, void *context, FAR void *arg)
+{
+  FAR struct esp32c3_spi_priv_s *priv = (FAR struct esp32c3_spi_priv_s *)arg;
+
+  esp32c3_spi_clr_regbits(SPI_DMA_INT_RAW_REG, SPI_TRANS_DONE_INT_RAW_M);
+  nxsem_post(&priv->sem_isr);
+
+  return 0;
+}
+#endif
+
+/****************************************************************************
  * Name: esp32c3_spibus_initialize
  *
  * Description:
@@ -1057,7 +1366,7 @@ static void esp32c3_spi_deinit(FAR struct spi_dev_s *dev)
  *   port     - Port number (for hardware that has multiple SPI interfaces)
  *
  * Returned Value:
- *   Valid SPI device structure reference on success; NULL on failure
+ *   Valid SPI device structure reference on success; NULL on failure.
  *
  ****************************************************************************/
 
@@ -1089,6 +1398,42 @@ FAR struct spi_dev_s *esp32c3_spibus_initialize(int port)
       return spi_dev;
     }
 
+#ifdef CONFIG_ESP32C3_SPI2_DMA
+  if (priv->cpuint != -ENOMEM)
+    {
+      /* Disable the provided CPU Interrupt to configure it. */
+
+      up_disable_irq(priv->cpuint);
+    }
+
+  priv->cpuint = esp32c3_request_irq(priv->config->periph,
+                                     ESP32C3_INT_PRIO_DEF,
+                                     ESP32C3_INT_LEVEL);
+  if (priv->cpuint < 0)
+    {
+      /* Failed to allocate a CPU interrupt of this type. */
+
+      leave_critical_section(flags);
+
+      return NULL;
+    }
+
+  if (irq_attach(priv->config->irq, esp32c3_spi_interrupt, priv) != OK)
+    {
+      /* Failed to attach IRQ, so CPU interrupt must be freed. */
+
+      esp32c3_free_cpuint(priv->config->periph);
+      priv->cpuint = -ENOMEM;
+      leave_critical_section(flags);
+
+      return NULL;
+    }
+
+  /* Enable the CPU interrupt that is linked to the SPI device. */
+
+  up_enable_irq(priv->cpuint);
+#endif
+
   esp32c3_spi_init(spi_dev);
 
   priv->refs++;
@@ -1108,7 +1453,7 @@ FAR struct spi_dev_s *esp32c3_spibus_initialize(int port)
  *   dev      - Device-specific state data
  *
  * Returned Value:
- *   Zero (OK) is returned on success.  Otherwise -1 (ERROR).
+ *   Zero (OK) is returned on success. Otherwise -1 (ERROR).
  *
  ****************************************************************************/
 
@@ -1134,6 +1479,14 @@ int esp32c3_spibus_uninitialize(FAR struct spi_dev_s 
*dev)
 
   leave_critical_section(flags);
 
+#ifdef CONFIG_ESP32C3_SPI2_DMA
+  up_disable_irq(priv->cpuint);
+  esp32c3_free_cpuint(priv->config->periph);
+  priv->cpuint = -ENOMEM;
+
+  nxsem_destroy(&priv->sem_isr);
+#endif
+
   esp32c3_spi_deinit(dev);
 
   nxsem_destroy(&priv->exclsem);

Reply via email to