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

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

commit 3813320c31787f84a6a75884b34a7bfdf3df42c4
Author: David Sidrane <[email protected]>
AuthorDate: Tue May 31 09:00:59 2022 -0700

    s32k1xx_edma:Add Looping and cleanup
    
    s32k1xx:EDMA Use aligned_data macros
    
    s32k1xx:EDMA CONFIG_ARCH_CHIP_S32K14x->CONFIG_ARCH_CHIP_S32K14X
    
    s32k1xx:EDMA remove FAR keyword
    
    s32k1xx:EDMA Fix C&P error from Kinetis
    
    s32k1xx:EDMA TCD Alignment of 32 Bytes to support Scatter/Gather
    
    s32k1xx:EDMA Fix access violation
    
    s32k1xx:dmamux fixed missing closing paren
---
 arch/arm/src/s32k1xx/Kconfig                      |   1 +
 arch/arm/src/s32k1xx/hardware/s32k1xx_dmamux.h    |   2 +-
 arch/arm/src/s32k1xx/hardware/s32k1xx_edma.h      |   6 +-
 arch/arm/src/s32k1xx/hardware/s32k1xx_memorymap.h |   4 +-
 arch/arm/src/s32k1xx/s32k1xx_edma.c               | 233 +++++++++-------------
 arch/arm/src/s32k1xx/s32k1xx_edma.h               |  33 ++-
 6 files changed, 121 insertions(+), 158 deletions(-)

diff --git a/arch/arm/src/s32k1xx/Kconfig b/arch/arm/src/s32k1xx/Kconfig
index 57ee616db5..a011e6002c 100644
--- a/arch/arm/src/s32k1xx/Kconfig
+++ b/arch/arm/src/s32k1xx/Kconfig
@@ -200,6 +200,7 @@ menu "S32K1XX Peripheral Selection"
 config S32K1XX_EDMA
        bool "eDMA"
        default n
+       select ARCH_DMA
 
 config S32K1XX_ENET
        bool "Ethernet"
diff --git a/arch/arm/src/s32k1xx/hardware/s32k1xx_dmamux.h 
b/arch/arm/src/s32k1xx/hardware/s32k1xx_dmamux.h
index 577bb2d0e8..23de5b8c65 100644
--- a/arch/arm/src/s32k1xx/hardware/s32k1xx_dmamux.h
+++ b/arch/arm/src/s32k1xx/hardware/s32k1xx_dmamux.h
@@ -36,7 +36,7 @@
 
 #if defined(CONFIG_ARCH_CHIP_S32K11X)
 #  define S32K1XX_NDMACH  4
-#elif defined(CONFIG_ARCH_CHIP_S32K14X
+#elif defined(CONFIG_ARCH_CHIP_S32K14X)
 #  define S32K1XX_NDMACH  16
 #endif
 
diff --git a/arch/arm/src/s32k1xx/hardware/s32k1xx_edma.h 
b/arch/arm/src/s32k1xx/hardware/s32k1xx_edma.h
index 1d8604584c..ff9bad7d4f 100644
--- a/arch/arm/src/s32k1xx/hardware/s32k1xx_edma.h
+++ b/arch/arm/src/s32k1xx/hardware/s32k1xx_edma.h
@@ -34,7 +34,7 @@
 
 #if defined(CONFIG_ARCH_CHIP_S32K11X)
 #  define S32K1XX_EDMA_NCHANNELS              4
-#elif defined(CONFIG_ARCH_CHIP_S32K14x)
+#elif defined(CONFIG_ARCH_CHIP_S32K14X)
 #  define S32K1XX_EDMA_NCHANNELS              16
 #else
 #  error "Unknown number of DMA channels for this S32K1xx part"
@@ -837,8 +837,8 @@
  * Public Types
  ****************************************************************************/
 
-/* In-memory representation of the 32-byte Transfer Control Descriptor
- * (TCD)
+/* Hardware representation of the 32-byte Transfer
+ * Control Descriptor (TCD)
  */
 
 struct s32k1xx_edmatcd_s
diff --git a/arch/arm/src/s32k1xx/hardware/s32k1xx_memorymap.h 
b/arch/arm/src/s32k1xx/hardware/s32k1xx_memorymap.h
index dc7e6f5b62..e12dec7a5a 100644
--- a/arch/arm/src/s32k1xx/hardware/s32k1xx_memorymap.h
+++ b/arch/arm/src/s32k1xx/hardware/s32k1xx_memorymap.h
@@ -34,8 +34,8 @@
 #define S32K1XX_AIPS_LITE_BASE   0x40000000  /* Peripheral bridge (AIPS-Lite) 
*/
 #  define S32K1XX_FLASHCFG_BASE  0x40000400  /* FLASH Configuration bytes */
 #  define S32K1XX_MSCM_BASE      0x40001000  /* MSCM */
-#  define S32K1XX_DMAC_BASE      0x40008000  /* DMA controller */
-#  define S32K1XX_DMADESC_BASE   0x40008000  /* DMA transfer control 
descriptors */
+#  define S32K1XX_EDMA_BASE      0x40008000  /* EDMA controller */
+#  define S32K1XX_EDMADESC_BASE  0x40008000  /* EDMA transfer control 
descriptors */
 #  define S32K1XX_MPU_BASE       0x4000d000  /* MPU */
 #  define S32K1XX_GPIOCTL_BASE   0x4000f000  /* GPIO controller */
 #  define S32K1XX_GPIOALIAS_BASE 0x400ff000  /* GPIO controller (alias) */
diff --git a/arch/arm/src/s32k1xx/s32k1xx_edma.c 
b/arch/arm/src/s32k1xx/s32k1xx_edma.c
index 1236b5fd9a..e0b0493ef3 100644
--- a/arch/arm/src/s32k1xx/s32k1xx_edma.c
+++ b/arch/arm/src/s32k1xx/s32k1xx_edma.c
@@ -86,22 +86,16 @@
  */
 
 #ifdef CONFIG_ARMV7M_DCACHE
-/* Align to the cache line size which we assume is >= 8 */
-
-#  define EDMA_ALIGN        ARMV7M_DCACHE_LINESIZE
-#  define EDMA_ALIGN_MASK   (EDMA_ALIGN-1)
-#  define EDMA_ALIGN_UP(n)  (((n) + EDMA_ALIGN_MASK) & ~EDMA_ALIGN_MASK)
-
+#  define EDMA_ALIGN  ARMV7M_DCACHE_LINESIZE
 #else
-/* Special alignment is not required in this case,
- * but we will align to 8-bytes
- */
+/* 32 byte alignment for TCDs is required for scatter gather */
 
-#  define EDMA_ALIGN        8
-#  define EDMA_ALIGN_MASK   7
-#  define EDMA_ALIGN_UP(n)  (((n) + 7) & ~7)
+#define EDMA_ALIGN        32
 #endif
 
+#define EDMA_ALIGN_MASK   (EDMA_ALIGN - 1)
+#define EDMA_ALIGN_UP(n)  (((n) + EDMA_ALIGN_MASK) & ~EDMA_ALIGN_MASK)
+
 /****************************************************************************
  * Private Types
  ****************************************************************************/
@@ -119,10 +113,10 @@ enum s32k1xx_dmastate_e
 
 struct s32k1xx_dmach_s
 {
-  uint8_t chan;                   /* DMA channel number 
(0-S32K1XX_EDMA_NCHANNELS) */
-  bool inuse;                     /* true: The DMA channel is in use */
-  uint8_t ttype;                  /* Transfer type: M2M, M2P, P2M, or P2P */
-  uint8_t state;                  /* Channel state.  See enum 
s32k1xx_dmastate_e */
+  uint8_t  chan;                  /* DMA channel number 
(0-S32K1XX_EDMA_NCHANNELS) */
+  bool     inuse;                 /* true: The DMA channel is in use */
+  uint8_t  state;                 /* Channel state.  See enum 
s32k1xx_dmastate_e */
+  uint8_t  dmamux;                /* The DMAMUX channel selection */
   uint32_t flags;                 /* DMA channel flags */
   edma_callback_t callback;       /* Callback invoked when the DMA completes */
   void *arg;                      /* Argument passed to callback function */
@@ -338,18 +332,13 @@ static inline void s32k1xx_tcd_chanlink(uint8_t flags,
 
   if (linkch == NULL || flags == EDMA_CONFIG_LINKTYPE_LINKNONE)
     {
-#if 0 /* Already done */
       /* No link or no link channel provided */
 
-      /* Disable minor links */
-
-      tcd->citer &= ~EDMA_TCD_CITER_ELINK;
-      tcd->biter &= ~EDMA_TCD_BITER_ELINK;
+      /* Disable minor links is done in s32k1xx_tcd_configure */
 
       /* Disable major link */
 
       tcd->csr   &= ~EDMA_TCD_CSR_MAJORELINK;
-#endif
     }
   else if (flags == EDMA_CONFIG_LINKTYPE_MINORLINK) /* Minor link config */
     {
@@ -405,13 +394,16 @@ static inline void s32k1xx_tcd_configure(struct 
s32k1xx_edmatcd_s *tcd,
   tcd->attr     = EDMA_TCD_ATTR_SSIZE(config->ssize) |  /* Transfer Attributes 
*/
                   EDMA_TCD_ATTR_DSIZE(config->dsize);
   tcd->nbytes   = config->nbytes;
-  tcd->slast    = tcd->slast;
+  tcd->slast    = config->flags & EDMA_CONFIG_LOOPSRC ?  -config->iter : 0;
   tcd->daddr    = config->daddr;
   tcd->doff     = config->doff;
   tcd->citer    = config->iter & EDMA_TCD_CITER_CITER_MASK;
   tcd->biter    = config->iter & EDMA_TCD_BITER_BITER_MASK;
-  tcd->csr      = EDMA_TCD_CSR_DREQ; /* Assume last transfer */
-  tcd->dlastsga = 0;
+  tcd->csr      = config->flags & EDMA_CONFIG_LOOP_MASK ?
+                                  0 : EDMA_TCD_CSR_DREQ;
+  tcd->csr      |= config->flags & EDMA_CONFIG_INTHALF ?
+                                  EDMA_TCD_CSR_INTHALF : 0;
+  tcd->dlastsga = config->flags & EDMA_CONFIG_LOOPDEST ?  -config->iter : 0;
 
   /* And special case flags */
 
@@ -440,6 +432,10 @@ static void s32k1xx_tcd_instantiate(struct s32k1xx_dmach_s 
*dmach,
 
   /* Push tcd into hardware TCD register */
 
+  /* Clear DONE bit first, otherwise ESG cannot be set */
+
+  putreg16(0,             base + S32K1XX_EDMA_TCD_CSR_OFFSET);
+
   putreg32(tcd->saddr,    base + S32K1XX_EDMA_TCD_SADDR_OFFSET);
   putreg16(tcd->soff,     base + S32K1XX_EDMA_TCD_SOFF_OFFSET);
   putreg16(tcd->attr,     base + S32K1XX_EDMA_TCD_ATTR_OFFSET);
@@ -450,9 +446,6 @@ static void s32k1xx_tcd_instantiate(struct s32k1xx_dmach_s 
*dmach,
   putreg16(tcd->citer,    base + S32K1XX_EDMA_TCD_CITER_ELINK_OFFSET);
   putreg32(tcd->dlastsga, base + S32K1XX_EDMA_TCD_DLASTSGA_OFFSET);
 
-  /* Clear DONE bit first, otherwise ESG cannot be set */
-
-  putreg16(0,             base + S32K1XX_EDMA_TCD_CSR_OFFSET);
   putreg16(tcd->csr,      base + S32K1XX_EDMA_TCD_CSR_OFFSET);
 
   putreg16(tcd->biter,    base + S32K1XX_EDMA_TCD_BITER_ELINK_OFFSET);
@@ -488,25 +481,25 @@ static void s32k1xx_dmaterminate(struct s32k1xx_dmach_s 
*dmach, int result)
   regval8         = EDMA_CERQ(chan);
   putreg8(regval8, S32K1XX_EDMA_CERQ);
 
-  /* Clear CSR to disable channel. Because if the given channel started,
-   * transfer CSR will be not zero. Because if it is the last transfer, DREQ
-   * will be set.  If not, ESG will be set.
-   */
-
   regaddr         = S32K1XX_EDMA_TCD_CSR(chan);
   putreg16(0, regaddr);
 
   /* Cancel next TCD transfer. */
 
   regaddr         = S32K1XX_EDMA_TCD_DLASTSGA(chan);
-  putreg16(0, regaddr);
+  putreg32(0, regaddr);
 
 #if CONFIG_S32K1XX_EDMA_NTCD > 0
   /* Return all allocated TCDs to the free list */
 
   for (tcd = dmach->head; tcd != NULL; tcd = next)
     {
-      next = (struct s32k1xx_edmatcd_s *)tcd->dlastsga;
+      /* If channel looped to itself we are done
+       * if not continue to free tcds in chain
+       */
+
+       next = dmach->flags & EDMA_CONFIG_LOOPDEST ?
+              NULL : (struct s32k1xx_edmatcd_s *)tcd->dlastsga;
       s32k1xx_tcd_free(tcd);
     }
 
@@ -514,15 +507,6 @@ static void s32k1xx_dmaterminate(struct s32k1xx_dmach_s 
*dmach, int result)
   dmach->tail = NULL;
 #endif
 
-  /* Check for an Rx (memory-to-peripheral/memory-to-memory) DMA transfer */
-
-  if (dmach->ttype == EMDA_MEM2MEM || dmach->ttype == EMDA_PERIPH2MEM)
-    {
-      /* Invalidate the cache to force reloads from memory. */
-
-#warning Missing logic
-    }
-
   /* Perform the DMA complete callback */
 
   if (dmach->callback)
@@ -556,13 +540,13 @@ static int s32k1xx_edma_interrupt(int irq, void *context, 
void *arg)
 {
   struct s32k1xx_dmach_s *dmach;
   uintptr_t regaddr;
-  uint32_t regval32;
-  uint16_t regval16;
-  uint8_t regval8;
-  uint8_t chan;
-  int result;
+  uint32_t  regval32;
+  uint16_t  regval16;
+  uint8_t   regval8;
+  uint8_t   chan;
+  int       result;
 
-  /* 'arg' should the DMA channel instance. */
+  /* 'arg' should be the DMA channel instance. */
 
   dmach = (struct s32k1xx_dmach_s *)arg;
   DEBUGASSERT(dmach != NULL);
@@ -584,7 +568,7 @@ static int s32k1xx_edma_interrupt(int irq, void *context, 
void *arg)
       /* Clear the pending eDMA channel interrupt */
 
       regval8 = EDMA_CINT(chan);
-      putreg32(regval8, S32K1XX_EDMA_CINT);
+      putreg8(regval8, S32K1XX_EDMA_CINT);
 
       /* Get the eDMA TCD Control and Status register value. */
 
@@ -604,7 +588,7 @@ static int s32k1xx_edma_interrupt(int irq, void *context, 
void *arg)
       else
         {
 #if CONFIG_S32K1XX_EDMA_NTCD > 0
-          /* Perform the end-of-major-cycle DMA callback */
+          /* Perform the half or end-of-major-cycle DMA callback */
 
           if (dmach->callback != NULL)
             {
@@ -612,7 +596,7 @@ static int s32k1xx_edma_interrupt(int irq, void *context, 
void *arg)
                               false, OK);
             }
 
-          return;
+          return OK;
 #else
           /* Otherwise the interrupt was not expected! */
 
@@ -623,8 +607,18 @@ static int s32k1xx_edma_interrupt(int irq, void *context, 
void *arg)
 
       /* Terminate the transfer when it is done. */
 
-      s32k1xx_dmaterminate(dmach, result);
+      if ((dmach->flags & EDMA_CONFIG_LOOP_MASK) == 0)
+        {
+          s32k1xx_dmaterminate(dmach, result);
+        }
+      else if (dmach->callback != NULL)
+        {
+          dmach->callback((DMACH_HANDLE)dmach, dmach->arg,
+                          true, result);
+        }
     }
+
+  return OK;
 }
 
 /****************************************************************************
@@ -661,7 +655,7 @@ static int s32k1xx_error_interrupt(int irq, void *context, 
void *arg)
           /* Clear the pending error interrupt status. */
 
           regval8 = EDMA_CERR(chan);
-          putreg32(regval8, S32K1XX_EDMA_CERR);
+          putreg8(regval8, S32K1XX_EDMA_CERR);
 
           /* Remove the bit from the sample ERR register so that perhaps we
            * can exit this loop early.
@@ -755,24 +749,12 @@ void weak_function arm_dma_initialize(void)
 
   /* Attach DMA interrupt vectors. */
 
-  irq_attach(S32K1XX_IRQ_DMACH0,  s32k1xx_edma_interrupt, &g_edma.dmach[0]);
-  irq_attach(S32K1XX_IRQ_DMACH1,  s32k1xx_edma_interrupt, &g_edma.dmach[1]);
-  irq_attach(S32K1XX_IRQ_DMACH2,  s32k1xx_edma_interrupt, &g_edma.dmach[2]);
-  irq_attach(S32K1XX_IRQ_DMACH3,  s32k1xx_edma_interrupt, &g_edma.dmach[3]);
-#if S32K1XX_EDMA_NCHANNELS > 4
-  irq_attach(S32K1XX_IRQ_DMACH4,  s32k1xx_edma_interrupt, &g_edma.dmach[4]);
-  irq_attach(S32K1XX_IRQ_DMACH5,  s32k1xx_edma_interrupt, &g_edma.dmach[5]);
-  irq_attach(S32K1XX_IRQ_DMACH6,  s32k1xx_edma_interrupt, &g_edma.dmach[6]);
-  irq_attach(S32K1XX_IRQ_DMACH7,  s32k1xx_edma_interrupt, &g_edma.dmach[7]);
-  irq_attach(S32K1XX_IRQ_DMACH8,  s32k1xx_edma_interrupt, &g_edma.dmach[8]);
-  irq_attach(S32K1XX_IRQ_DMACH9,  s32k1xx_edma_interrupt, &g_edma.dmach[9]);
-  irq_attach(S32K1XX_IRQ_DMACH10, s32k1xx_edma_interrupt, &g_edma.dmach[10]);
-  irq_attach(S32K1XX_IRQ_DMACH11, s32k1xx_edma_interrupt, &g_edma.dmach[11]);
-  irq_attach(S32K1XX_IRQ_DMACH12, s32k1xx_edma_interrupt, &g_edma.dmach[12]);
-  irq_attach(S32K1XX_IRQ_DMACH13, s32k1xx_edma_interrupt, &g_edma.dmach[13]);
-  irq_attach(S32K1XX_IRQ_DMACH14, s32k1xx_edma_interrupt, &g_edma.dmach[14]);
-  irq_attach(S32K1XX_IRQ_DMACH15, s32k1xx_edma_interrupt, &g_edma.dmach[15]);
-#endif
+  for (i = 0; i < S32K1XX_EDMA_NCHANNELS; i++)
+    {
+      irq_attach(S32K1XX_IRQ_DMACH0 + i,
+                 s32k1xx_edma_interrupt, &g_edma.dmach[i]);
+    }
+
   /* Attach the DMA error interrupt vector */
 
   irq_attach(S32K1XX_IRQ_DMACH_ERR, s32k1xx_error_interrupt, NULL);
@@ -790,6 +772,14 @@ void weak_function arm_dma_initialize(void)
 
       regaddr = S32K1XX_EDMA_TCD_CSR(i);
       putreg16(0, regaddr);
+
+      /* Set all TCD entries to 0 so that biter and citer
+       * will be 0 when DONE is not set so that s32k1xx_dmach_getcount
+       * reports 0.
+       */
+
+      memset((void *)S32K1XX_EDMA_TCD_BASE(i), 0,
+             sizeof(struct s32k1xx_edmatcd_s));
     }
 
   /* Clear all pending DMA channel interrupts */
@@ -800,24 +790,10 @@ void weak_function arm_dma_initialize(void)
    * controller).
    */
 
-  up_enable_irq(S32K1XX_IRQ_DMACH0);
-  up_enable_irq(S32K1XX_IRQ_DMACH1);
-  up_enable_irq(S32K1XX_IRQ_DMACH2);
-  up_enable_irq(S32K1XX_IRQ_DMACH3);
-#if S32K1XX_EDMA_NCHANNELS > 4
-  up_enable_irq(S32K1XX_IRQ_DMACH4);
-  up_enable_irq(S32K1XX_IRQ_DMACH5);
-  up_enable_irq(S32K1XX_IRQ_DMACH6);
-  up_enable_irq(S32K1XX_IRQ_DMACH7);
-  up_enable_irq(S32K1XX_IRQ_DMACH8);
-  up_enable_irq(S32K1XX_IRQ_DMACH9);
-  up_enable_irq(S32K1XX_IRQ_DMACH10);
-  up_enable_irq(S32K1XX_IRQ_DMACH11);
-  up_enable_irq(S32K1XX_IRQ_DMACH12);
-  up_enable_irq(S32K1XX_IRQ_DMACH13);
-  up_enable_irq(S32K1XX_IRQ_DMACH14);
-  up_enable_irq(S32K1XX_IRQ_DMACH15);
-#endif
+  for (i = 0; i < S32K1XX_EDMA_NCHANNELS; i++)
+    {
+      up_enable_irq(S32K1XX_IRQ_DMACH0 + i);
+    }
 
   /* Enable the DMA error interrupt */
 
@@ -837,7 +813,6 @@ void weak_function arm_dma_initialize(void)
  *            Settings include:
  *
  *            DMAMUX_CHCFG_SOURCE     Chip-specific DMA source (required)
- *            DMAMUX_CHCFG_AON        DMA Channel Always Enable (optional)
  *            DMAMUX_CHCFG_TRIG       DMA Channel Trigger Enable (optional)
  *            DMAMUX_CHCFG_ENBL       DMA Mux Channel Enable (required)
  *
@@ -858,7 +833,7 @@ void weak_function arm_dma_initialize(void)
  *
  ****************************************************************************/
 
-DMACH_HANDLE s32k1xx_dmach_alloc(uint32_t dmamux, uint8_t dchpri)
+DMACH_HANDLE s32k1xx_dmach_alloc(uint8_t dmamux, uint8_t dchpri)
 {
   struct s32k1xx_dmach_s *dmach;
   unsigned int chndx;
@@ -884,6 +859,7 @@ DMACH_HANDLE s32k1xx_dmach_alloc(uint32_t dmamux, uint8_t 
dchpri)
           dmach        = candidate;
           dmach->inuse = true;
           dmach->state = S32K1XX_DMA_IDLE;
+          dmach->dmamux = dmamux;
 
           /* Clear any pending interrupts on the channel */
 
@@ -896,10 +872,9 @@ DMACH_HANDLE s32k1xx_dmach_alloc(uint32_t dmamux, uint8_t 
dchpri)
           regval8 = EDMA_CERQ(chndx);
           putreg8(regval8, S32K1XX_EDMA_CERQ);
 
-          /* Set the DMAMUX register associated with this channel */
+          /* Disable the associated DMAMUX for now */
 
-          regaddr = S32K1XX_DMAMUX_CHCFG(chndx);
-          putreg32(dmamux, regaddr);
+          putreg8(0, S32K1XX_DMAMUX_CHCFG(chndx));
           break;
         }
     }
@@ -936,7 +911,6 @@ DMACH_HANDLE s32k1xx_dmach_alloc(uint32_t dmamux, uint8_t 
dchpri)
 void s32k1xx_dmach_free(DMACH_HANDLE handle)
 {
   struct s32k1xx_dmach_s *dmach = (struct s32k1xx_dmach_s *)handle;
-  uintptr_t regaddr;
   uint8_t regval8;
 
   dmainfo("dmach: %p\n", dmach);
@@ -958,8 +932,7 @@ void s32k1xx_dmach_free(DMACH_HANDLE handle)
 
   /* Disable the associated DMAMUX */
 
-  regaddr = S32K1XX_DMAMUX_CHCFG(dmach->chan);
-  putreg32(0, regaddr);
+  putreg8(0, S32K1XX_DMAMUX_CHCFG(dmach->chan));
 }
 
 /****************************************************************************
@@ -995,12 +968,16 @@ int s32k1xx_dmach_xfrsetup(DMACH_HANDLE *handle,
 #if CONFIG_S32K1XX_EDMA_NTCD > 0
   struct s32k1xx_edmatcd_s *tcd;
   struct s32k1xx_edmatcd_s *prev;
+  uint16_t mask = config->flags & EDMA_CONFIG_INTMAJOR ? 0 :
+                                  EDMA_TCD_CSR_INTMAJOR;
 #endif
   uintptr_t regaddr;
   uint16_t regval16;
 
   DEBUGASSERT(dmach != NULL);
-  dmainfo("dmach%u: %p config: %p\n", dmach, config);
+  dmainfo("dmach%u: %p config: %p\n", dmach->chan, dmach, config);
+
+  dmach->flags  = config->flags;
 
 #if CONFIG_S32K1XX_EDMA_NTCD > 0
   /* Scatter/gather DMA is supported */
@@ -1029,7 +1006,6 @@ int s32k1xx_dmach_xfrsetup(DMACH_HANDLE *handle,
 
       dmach->head  = tcd;
       dmach->tail  = tcd;
-      dmach->ttype = config->ttype;
 
       /* And instantiate the first TCD in the DMA channel TCD registers. */
 
@@ -1037,11 +1013,9 @@ int s32k1xx_dmach_xfrsetup(DMACH_HANDLE *handle,
     }
   else
     {
-      /* Cannot mix transfer types (only because of cache-related operations.
-       * this restriction could be removed with some effort).
-       */
+      /* Cannot mix transfer types */
 
-      if (dmach->ttype != config->ttype)
+      if (dmach->flags & EDMA_CONFIG_LOOP_MASK)
         {
           s32k1xx_tcd_free(tcd);
           return -EINVAL;
@@ -1053,8 +1027,9 @@ int s32k1xx_dmach_xfrsetup(DMACH_HANDLE *handle,
 
       prev           = dmach->tail;
       regval16       = prev->csr;
-      regval16      &= ~EDMA_TCD_CSR_DREQ;
+      regval16      &= ~(EDMA_TCD_CSR_DREQ | mask);
       regval16      |= EDMA_TCD_CSR_ESG;
+
       prev->csr      = regval16;
 
       prev->dlastsga = (uint32_t)tcd;
@@ -1076,7 +1051,7 @@ int s32k1xx_dmach_xfrsetup(DMACH_HANDLE *handle,
 
           regaddr   = S32K1XX_EDMA_TCD_CSR(dmach->chan);
           regval16  = getreg16(regaddr);
-          regval16 &= ~EDMA_TCD_CSR_DREQ;
+          regval16 &= ~(EDMA_TCD_CSR_DREQ | mask);
           regval16 |= EDMA_TCD_CSR_ESG;
           putreg16(regval16, regaddr);
 
@@ -1115,34 +1090,9 @@ int s32k1xx_dmach_xfrsetup(DMACH_HANDLE *handle,
   modifyreg16(regaddr, 0, EDMA_TCD_CSR_INTMAJOR);
 #endif
 
-  /* Check for an Rx (memory-to-peripheral/memory-to-memory) DMA transfer */
+  /* Set the DMAMUX source and enable and optional trigger */
 
-  if (dmach->ttype == EMDA_MEM2MEM || dmach->ttype == EMDA_PERIPH2MEM)
-    {
-      /* Invalidate caches associated with the destination DMA memory.
-       * REVISIT:  nbytes is the number of bytes transferred on each
-       * minor loop.  The following is only valid when the major loop
-       * is one.
-       */
-
-      up_invalidate_dcache((uintptr_t)config->daddr,
-                           (uintptr_t)config->daddr + config->nbytes);
-    }
-
-  /* Check for an Tx (peripheral-to-memory/memory-to-memory) DMA transfer */
-
-  if (dmach->ttype == EMDA_MEM2MEM || dmach->ttype == EMDA_MEM2PERIPH)
-    {
-      /* Clean caches associated with the source DMA memory.
-       * REVISIT:  nbytes is the number of bytes transferred on each
-       * minor loop.  The following is only valid when the major loop
-       * is one.
-       */
-#warning Missing logic
-
-      up_clean_dcache((uintptr_t)config->saddr,
-                      (uintptr_t)config->saddr + config->nbytes);
-    }
+  putreg8(dmach->dmamux, S32K1XX_DMAMUX_CHCFG(dmach->chan));
 
   dmach->state = S32K1XX_DMA_CONFIGURED;
   return OK;
@@ -1155,10 +1105,10 @@ int s32k1xx_dmach_xfrsetup(DMACH_HANDLE *handle,
  *   Start the DMA transfer.  This function should be called after the final
  *   call to s32k1xx_dmach_xfrsetup() in order to avoid race conditions.
  *
- *   At the conclusion of each major DMA loop, a callback to the user
- *   provided function is made:  |For "normal" DMAs, this will correspond to
- *   the DMA DONE interrupt; for scatter gather DMAs, multiple interrupts
- *   will be generated with the final being the DONE interrupt.
+ *   At the conclusion of each major DMA loop, a callback to
+ *   the user-provided function is made: For "normal" DMAs, this will
+ *   correspond to the DMA DONE interrupt; for scatter gather DMAs,
+ *   this will be generated with the final TCD.
  *
  *   At the conclusion of the DMA, the DMA channel is reset, all TCDs are
  *   freed, and the callback function is called with the the success/fail
@@ -1191,14 +1141,13 @@ int s32k1xx_dmach_start(DMACH_HANDLE handle, 
edma_callback_t callback,
 
   DEBUGASSERT(dmach != NULL && dmach->state == S32K1XX_DMA_CONFIGURED);
   chan            = dmach->chan;
-  dmainfo("dmach%u: %p callback: %p arg: %p\n", dmach, chan, callback, arg);
+  dmainfo("dmach%u: %p callback: %p arg: %p\n", chan, dmach, callback, arg);
 
   /* Save the callback info.  This will be invoked when the DMA completes */
 
   flags           = spin_lock_irqsave(NULL);
   dmach->callback = callback;
   dmach->arg      = arg;
-  dmach->state    = S32K1XX_DMA_ACTIVE;
 
 #if CONFIG_S32K1XX_EDMA_NTCD > 0
   /* Although it is not recommended, it might be possible to call this
@@ -1208,6 +1157,8 @@ int s32k1xx_dmach_start(DMACH_HANDLE handle, 
edma_callback_t callback,
   if (dmach->state != S32K1XX_DMA_ACTIVE)
 #endif
     {
+      dmach->state    = S32K1XX_DMA_ACTIVE;
+
       /* Enable channel ERROR interrupts */
 
       regval8         = EDMA_SEEI(chan);
@@ -1216,7 +1167,7 @@ int s32k1xx_dmach_start(DMACH_HANDLE handle, 
edma_callback_t callback,
       /* Enable the DMA request for this channel */
 
       regval8         = EDMA_SERQ(chan);
-      putreg8(regval8, S32K1XX_EDMA_SERQ_OFFSET);
+      putreg8(regval8, S32K1XX_EDMA_SERQ);
     }
 
   spin_unlock_irqrestore(NULL, flags);
diff --git a/arch/arm/src/s32k1xx/s32k1xx_edma.h 
b/arch/arm/src/s32k1xx/s32k1xx_edma.h
index cd29a6d4e2..ac85a0a03f 100644
--- a/arch/arm/src/s32k1xx/s32k1xx_edma.h
+++ b/arch/arm/src/s32k1xx/s32k1xx_edma.h
@@ -122,6 +122,18 @@
 #  define EDMA_CONFIG_LINKTYPE_MINORLINK (1 << EDMA_CONFIG_LINKTYPE_SHIFT) /* 
Channel link after each minor loop */
 #  define EDMA_CONFIG_LINKTYPE_MAJORLINK (2 << EDMA_CONFIG_LINKTYPE_SHIFT) /* 
Channel link when major loop count exhausted */
 
+#define EDMA_CONFIG_LOOP_SHIFT           (2) /* Bits 2-3: Loop type */
+#define EDMA_CONFIG_LOOP_MASK            (3 << EDMA_CONFIG_LOOP_SHIFT)
+#  define EDMA_CONFIG_LOOPNONE           (0 << EDMA_CONFIG_LOOP_SHIFT) /* No 
looping */
+#  define EDMA_CONFIG_LOOPSRC            (1 << EDMA_CONFIG_LOOP_SHIFT) /* 
Source looping */
+#  define EDMA_CONFIG_LOOPDEST           (2 << EDMA_CONFIG_LOOP_SHIFT) /* Dest 
looping */
+
+#define EDMA_CONFIG_INTHALF              (1 << 4) /* Bits 4: Int on HALF */
+#define EDMA_CONFIG_INTMAJOR             (1 << 5) /* Bits 5: Int on all Major 
completion
+                                                   * Default is only on last 
completion
+                                                   * if using scatter gather
+                                                   */
+
 /****************************************************************************
  * Public Types
  ****************************************************************************/
@@ -130,19 +142,19 @@ typedef void *DMACH_HANDLE;
 typedef void (*edma_callback_t)(DMACH_HANDLE handle,
                                 void *arg, bool done, int result);
 
-/* eDMA transfer type */
-
-enum s32k1xx_edma_xfrtype_e
-{
-  EDMA_MEM2MEM = 0,      /* Transfer from memory to memory */
-  EDMA_PERIPH2MEM,       /* Transfer from peripheral to memory */
-  EDMA_MEM2PERIPH,       /* Transfer from memory to peripheral */
-};
-
 /* This structure holds the source/destination transfer attribute
  * configuration.
  */
 
+/* eDMA transfer sizes */
+
+enum s32k1xx_edma_sizes_e
+{
+  EDMA_8BIT    = 0,      /* Transfer data size 8 */
+  EDMA_16BIT   = 1,      /* Transfer data size 16 */
+  EDMA_32BIT   = 2,      /* Transfer data size 32 */
+};
+
 struct s32k1xx_edma_xfrconfig_s
 {
     uint32_t saddr;      /* Source data address. */
@@ -153,7 +165,6 @@ struct s32k1xx_edma_xfrconfig_s
     uint8_t  flags;      /* See EDMA_CONFIG_* definitions */
     uint8_t  ssize;      /* Source data transfer size (see TCD_ATTR_SIZE_* 
definitions in rdware/. */
     uint8_t  dsize;      /* Destination data transfer size. */
-    uint8_t  ttype;      /* Transfer type (see enum s32k1xx_edma_xfrtype_e). */
 #ifdef CONFIG_S32K1XX_EDMA_EMLIM
     uint16_t nbytes;     /* Bytes to transfer in a minor loop */
 #else
@@ -264,7 +275,7 @@ extern "C"
  *
  ****************************************************************************/
 
-DMACH_HANDLE s32k1xx_dmach_alloc(uint32_t dmamux, uint8_t dchpri);
+DMACH_HANDLE s32k1xx_dmach_alloc(uint8_t dmamux, uint8_t dchpri);
 
 /****************************************************************************
  * Name: s32k1xx_dmach_free

Reply via email to