diff --git a/arch/arm/src/kinetis/hardware/kinetis_edma.h b/arch/arm/src/kinetis/hardware/kinetis_edma.h
index c21c0d9f01..0c1f1a1fd8 100644
--- a/arch/arm/src/kinetis/hardware/kinetis_edma.h
+++ b/arch/arm/src/kinetis/hardware/kinetis_edma.h
@@ -831,14 +831,12 @@
  * Public Types
  ****************************************************************************/
 
-/* In-memory representation of the 32-byte Transfer Control Descriptor
- * (TCD)
+/* Hardware representation of the 32-byte Transfer
+ * Control Descriptor (TCD)
  */
 
 struct kinetis_edmatcd_s
 {
-  sq_entry_t node;
-  uint8_t    flags;         /* See EDMA_CONFIG_* definitions */
   uint32_t   saddr;         /* Offset: 0x0000  TCD Source Address */
   uint16_t   soff;          /* Offset: 0x0004  TCD Signed Source Address Offset */
   uint16_t   attr;          /* Offset: 0x0006  TCD Transfer Attributes */
diff --git a/arch/arm/src/kinetis/kinetis_edma.c b/arch/arm/src/kinetis/kinetis_edma.c
index d8925b067c..5a57f62f54 100644
--- a/arch/arm/src/kinetis/kinetis_edma.c
+++ b/arch/arm/src/kinetis/kinetis_edma.c
@@ -88,22 +88,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
  ****************************************************************************/
@@ -121,11 +115,10 @@ enum kinetis_dmastate_e
 
 struct kinetis_dmach_s
 {
-  uint8_t chan;                   /* DMA channel number (0-KINETIS_EDMA_NCHANNELS) */
-  bool inuse;                     /* true: The DMA channel is in use */
-  uint8_t dmamux;                 /* The DMAMUX channel selection */
-  uint8_t ttype;                  /* Transfer type: M2M, M2P, P2M, or P2P */
-  uint8_t state;                  /* Channel state.  See enum kinetis_dmastate_e */
+  uint8_t  chan;                  /* DMA channel number (0-KINETIS_EDMA_NCHANNELS) */
+  bool     inuse;                 /* true: The DMA channel is in use */
+  uint8_t  state;                 /* Channel state.  See enum kinetis_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 */
@@ -341,18 +334,13 @@ static inline void kinetis_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 kinetis_tcd_configure */
 
       /* Disable major link */
 
       tcd->csr   &= ~EDMA_TCD_CSR_MAJORELINK;
-#endif
     }
   else if (flags == EDMA_CONFIG_LINKTYPE_MINORLINK) /* Minor link config */
     {
@@ -403,22 +391,21 @@ static inline void kinetis_tcd_chanlink(uint8_t flags,
 static inline void kinetis_tcd_configure(struct kinetis_edmatcd_s *tcd,
                             const struct kinetis_edma_xfrconfig_s *config)
 {
-  tcd->flags    = config->flags;
   tcd->saddr    = config->saddr;
   tcd->soff     = config->soff;
   tcd->attr     = EDMA_TCD_ATTR_SSIZE(config->ssize) |  /* Transfer Attributes */
                   EDMA_TCD_ATTR_DSIZE(config->dsize);
   tcd->nbytes   = config->nbytes;
-  tcd->slast    = config->flags & EDMA_CONFIG_LOOPSRC ?  -config->iter : 0;
+  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      = config->flags & EDMA_CONFIG_LOOPDEST ?
+  tcd->csr      = config->flags & EDMA_CONFIG_LOOP_MASK ?
                                   0 : EDMA_TCD_CSR_DREQ;
-  tcd->csr      |= config->flags & EDMA_CONFIG_INTHALF ?
+  tcd->csr     |= config->flags & EDMA_CONFIG_INTHALF ?
                                   EDMA_TCD_CSR_INTHALF : 0;
-  tcd->dlastsga = config->flags & EDMA_CONFIG_LOOPDEST ?  -config->iter : 0;
+  tcd->dlastsga = config->flags & EDMA_CONFIG_LOOPDEST ? -config->iter : 0;
 
   /* And special case flags */
 
@@ -447,6 +434,10 @@ static void kinetis_tcd_instantiate(struct kinetis_dmach_s *dmach,
 
   /* Push tcd into hardware TCD register */
 
+  /* Clear DONE bit first, otherwise ESG cannot be set */
+
+  putreg16(0,             base + KINETIS_EDMA_TCD_CSR_OFFSET);
+
   putreg32(tcd->saddr,    base + KINETIS_EDMA_TCD_SADDR_OFFSET);
   putreg16(tcd->soff,     base + KINETIS_EDMA_TCD_SOFF_OFFSET);
   putreg16(tcd->attr,     base + KINETIS_EDMA_TCD_ATTR_OFFSET);
@@ -457,9 +448,6 @@ static void kinetis_tcd_instantiate(struct kinetis_dmach_s *dmach,
   putreg16(tcd->citer,    base + KINETIS_EDMA_TCD_CITER_ELINK_OFFSET);
   putreg32(tcd->dlastsga, base + KINETIS_EDMA_TCD_DLASTSGA_OFFSET);
 
-  /* Clear DONE bit first, otherwise ESG cannot be set */
-
-  putreg16(0,             base + KINETIS_EDMA_TCD_CSR_OFFSET);
   putreg16(tcd->csr,      base + KINETIS_EDMA_TCD_CSR_OFFSET);
 
   putreg16(tcd->biter,    base + KINETIS_EDMA_TCD_BITER_ELINK_OFFSET);
@@ -495,34 +483,13 @@ static void kinetis_dmaterminate(struct kinetis_dmach_s *dmach, int result)
   regval8         = EDMA_CERQ(chan);
   putreg8(regval8, KINETIS_EDMA_CERQ);
 
-  /* Check for an Rx (memory-to-peripheral/memory-to-memory) DMA transfer */
-
-  if (dmach->ttype == EDMA_MEM2MEM || dmach->ttype == EDMA_PERIPH2MEM)
-    {
-      /* Invalidate the cache to force reloads from memory. */
-
-#warning Missing logic
-    }
-
-  /* Perform the DMA complete callback */
-
-  if (dmach->callback)
-    {
-      dmach->callback((DMACH_HANDLE)dmach, dmach->arg, true, result);
-    }
-
-  /* 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         = KINETIS_EDMA_TCD_CSR(chan);
   putreg16(0, regaddr);
 
   /* Cancel next TCD transfer. */
 
   regaddr         = KINETIS_EDMA_TCD_DLASTSGA(chan);
-  putreg16(0, regaddr);
+  putreg32(0, regaddr);
 
 #if CONFIG_KINETIS_EDMA_NTCD > 0
   /* Return all allocated TCDs to the free list */
@@ -533,7 +500,7 @@ static void kinetis_dmaterminate(struct kinetis_dmach_s *dmach, int result)
        * if not continue to free tcds in chain
        */
 
-       next = tcd->flags & EDMA_CONFIG_LOOPDEST ?
+       next = dmach->flags & EDMA_CONFIG_LOOPDEST ?
               NULL : (struct kinetis_edmatcd_s *)tcd->dlastsga;
 
        kinetis_tcd_free(tcd);
@@ -543,6 +510,13 @@ static void kinetis_dmaterminate(struct kinetis_dmach_s *dmach, int result)
   dmach->tail = NULL;
 #endif
 
+  /* Perform the DMA complete callback */
+
+  if (dmach->callback)
+    {
+      dmach->callback((DMACH_HANDLE)dmach, dmach->arg, true, result);
+    }
+
   dmach->callback = NULL;
   dmach->arg      = NULL;
   dmach->state    = KINETIS_DMA_IDLE;
@@ -569,13 +543,13 @@ static int kinetis_edma_interrupt(int irq, void *context, void *arg)
 {
   struct kinetis_dmach_s *dmach;
   uintptr_t regaddr;
-  uint8_t   regval8;
-  uint16_t  regval16;
   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 kinetis_dmach_s *)arg;
   DEBUGASSERT(dmach != NULL);
@@ -617,12 +591,12 @@ static int kinetis_edma_interrupt(int irq, void *context, void *arg)
       else
         {
 #if CONFIG_KINETIS_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)
             {
               dmach->callback((DMACH_HANDLE)dmach, dmach->arg,
-                              false, 0);
+                              false, OK);
             }
 
           return OK;
@@ -636,7 +610,15 @@ static int kinetis_edma_interrupt(int irq, void *context, void *arg)
 
       /* Terminate the transfer when it is done. */
 
-      kinetis_dmaterminate(dmach, result);
+      if ((dmach->flags & EDMA_CONFIG_LOOP_MASK) == 0)
+        {
+          kinetis_dmaterminate(dmach, result);
+        }
+      else if (dmach->callback != NULL)
+        {
+          dmach->callback((DMACH_HANDLE)dmach, dmach->arg,
+                          true, result);
+        }
     }
 
   return OK;
@@ -805,6 +787,14 @@ void weak_function arm_dma_initialize(void)
 
       regaddr = KINETIS_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 kinetis_dmach_getcount
+       * reports 0.
+       */
+
+      memset((void *)KINETIS_EDMA_TCD_BASE(i), 0,
+             sizeof(struct kinetis_edmatcd_s));
     }
 
   /* Clear all pending DMA channel interrupts */
@@ -993,6 +983,8 @@ int kinetis_dmach_xfrsetup(DMACH_HANDLE *handle,
 #if CONFIG_KINETIS_EDMA_NTCD > 0
   struct kinetis_edmatcd_s *tcd;
   struct kinetis_edmatcd_s *prev;
+  uint16_t mask  =  config->flags & EDMA_CONFIG_INTMAJOR ? 0 :
+                                    EDMA_TCD_CSR_INTMAJOR;
 #endif
   uintptr_t regaddr;
   uint16_t regval16;
@@ -1000,6 +992,8 @@ int kinetis_dmach_xfrsetup(DMACH_HANDLE *handle,
   DEBUGASSERT(dmach != NULL);
   dmainfo("dmach%u: %p config: %p\n", dmach->chan, dmach, config);
 
+  dmach->flags = config->flags;
+
 #if CONFIG_KINETIS_EDMA_NTCD > 0
   /* Scatter/gather DMA is supported */
 
@@ -1019,20 +1013,6 @@ int kinetis_dmach_xfrsetup(DMACH_HANDLE *handle,
 
   tcd->csr |= EDMA_TCD_CSR_INTMAJOR;
 
-  /* Is looped to it's self? */
-
-  if (config->flags & EDMA_CONFIG_LOOP_MASK)
-    {
-      /* Enable major link */
-
-      tcd->csr |= EDMA_TCD_CSR_MAJORELINK;
-
-      /* Set major linked channel back to this one */
-
-      tcd->csr   &= ~EDMA_TCD_CSR_MAJORLINKCH_MASK;
-      tcd->csr   |=  EDMA_TCD_CSR_MAJORLINKCH(dmach->chan);
-    }
-
   /* Is this the first descriptor in the list? */
 
   if (dmach->head == NULL)
@@ -1041,7 +1021,6 @@ int kinetis_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. */
 
@@ -1049,12 +1028,9 @@ int kinetis_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 ||
-          dmach->flags & EDMA_CONFIG_LOOPDEST)
+      if (dmach->flags & EDMA_CONFIG_LOOP_MASK)
         {
           kinetis_tcd_free(tcd);
           return -EINVAL;
@@ -1066,8 +1042,9 @@ int kinetis_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;
@@ -1089,7 +1066,7 @@ int kinetis_dmach_xfrsetup(DMACH_HANDLE *handle,
 
           regaddr   = KINETIS_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);
 
@@ -1128,35 +1105,6 @@ int kinetis_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 */
-
-  if (dmach->ttype == EDMA_MEM2MEM || dmach->ttype == EDMA_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 == EDMA_MEM2MEM || dmach->ttype == EDMA_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);
-    }
-
   /* Set the DMAMUX source and enable and optional trigger */
 
   putreg8(dmach->dmamux, KINETIS_DMAMUX_CHCFG(dmach->chan));
@@ -1172,10 +1120,10 @@ int kinetis_dmach_xfrsetup(DMACH_HANDLE *handle,
  *   Start the DMA transfer.  This function should be called after the final
  *   call to kinetis_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
diff --git a/arch/arm/src/kinetis/kinetis_edma.h b/arch/arm/src/kinetis/kinetis_edma.h
index f12ac414e5..f5a9909edb 100644
--- a/arch/arm/src/kinetis/kinetis_edma.h
+++ b/arch/arm/src/kinetis/kinetis_edma.h
@@ -122,13 +122,17 @@
 #  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: Loop type */
+#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 << 3) /* Bits 3: Int on HALF */
+#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
@@ -138,16 +142,7 @@ typedef void *DMACH_HANDLE;
 typedef void (*edma_callback_t)(DMACH_HANDLE handle,
                                 void *arg, bool done, int result);
 
-/* eDMA transfer type */
-
-enum kinetis_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 */
-};
-
-/* eDMA transfer sises */
+/* eDMA transfer sizes */
 
 enum kinetis_edma_sizes_e
 {
@@ -170,7 +165,6 @@ struct kinetis_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 kinetis_edma_xfrtype_e). */
 #ifdef CONFIG_KINETIS_EDMA_EMLIM
     uint16_t nbytes;     /* Bytes to transfer in a minor loop */
 #else