You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2022/08/06 07:32:11 UTC

[incubator-nuttx] branch master updated (22d41f6b9c -> 55aaba53fc)

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

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


    from 22d41f6b9c LPC17xx_40xx PWM multichannel support USB no softconnect SocketCAN kconfig fixes
     new f34acdb936 imxrt:lpi2c add parens for macros expansions
     new 85ec2e1446 imxrt:Add LPI2C DMA
     new fa58381e58 imxrt:serial add TX & RX DMA support
     new 55aaba53fc imxrt:SPI add DMA support

The 4 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 arch/arm/src/imxrt/Kconfig                |   88 ++
 arch/arm/src/imxrt/hardware/imxrt_lpi2c.h |   60 +-
 arch/arm/src/imxrt/imxrt_lpi2c.c          |  543 ++++++++-
 arch/arm/src/imxrt/imxrt_lpspi.c          |  416 ++++++-
 arch/arm/src/imxrt/imxrt_serial.c         | 1798 +++++++++++++++++++++++------
 arch/arm/src/imxrt/imxrt_serial.h         |  184 +++
 6 files changed, 2679 insertions(+), 410 deletions(-)


[incubator-nuttx] 02/04: imxrt:Add LPI2C DMA

Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 85ec2e1446b55f679cdf0aad6cfcd521eeceb6db
Author: David Sidrane <Da...@NscDg.com>
AuthorDate: Wed Jun 1 14:01:30 2022 -0700

    imxrt:Add LPI2C DMA
---
 arch/arm/src/imxrt/Kconfig       |  39 +++
 arch/arm/src/imxrt/imxrt_lpi2c.c | 543 ++++++++++++++++++++++++++++++++++++---
 2 files changed, 548 insertions(+), 34 deletions(-)

diff --git a/arch/arm/src/imxrt/Kconfig b/arch/arm/src/imxrt/Kconfig
index 4b7c010a9e..b8608c1511 100644
--- a/arch/arm/src/imxrt/Kconfig
+++ b/arch/arm/src/imxrt/Kconfig
@@ -804,6 +804,11 @@ config LPI2C1_BUSYIDLE
 	int "Bus idle timeout period in clock cycles"
 	default 0
 
+config LPI2C1_DMA
+	bool "Enable DMA for I2C1"
+	default n
+	depends on IMXRT_LPI2C_DMA
+
 config LPI2C1_FILTSCL
 	int "I2C master digital glitch filters for SCL input in clock cycles"
 	default 0
@@ -825,6 +830,11 @@ config LPI2C2_BUSYIDLE
 	int "Bus idle timeout period in clock cycles"
 	default 0
 
+config LPI2C2_DMA
+	bool "Enable DMA for I2C2"
+	default n
+	depends on IMXRT_LPI2C_DMA
+
 config LPI2C2_FILTSCL
 	int "I2C master digital glitch filters for SCL input in clock cycles"
 	default 0
@@ -846,6 +856,11 @@ config LPI2C3_BUSYIDLE
 	int "Bus idle timeout period in clock cycles"
 	default 0
 
+config LPI2C3_DMA
+	bool "Enable DMA for I2C3"
+	default n
+	depends on IMXRT_LPI2C_DMA
+
 config LPI2C3_FILTSCL
 	int "I2C master digital glitch filters for SCL input in clock cycles"
 	default 0
@@ -867,6 +882,11 @@ config LPI2C4_BUSYIDLE
 	int "Bus idle timeout period in clock cycles"
 	default 0
 
+config LPI2C4_DMA
+	bool "Enable DMA for I2C4"
+	default n
+	depends on IMXRT_LPI2C_DMA
+
 config LPI2C4_FILTSCL
 	int "I2C master digital glitch filters for SCL input in clock cycles"
 	default 0
@@ -1591,6 +1611,25 @@ endmenu # Memory Configuration
 menu "LPI2C Configuration"
 	depends on IMXRT_LPI2C
 
+config IMXRT_LPI2C_DMA
+	bool "I2C DMA Support"
+	default n
+	depends on IMXRT_LPI2C && IMXRT_EDMA && !I2C_POLLED
+	---help---
+		This option enables the DMA for I2C transfers.
+		Note: The user can define CONFIG_I2C_DMAPRIO: a custom priority value
+		for the I2C dma streams, else the default priority level is set to
+		medium.
+
+config IMXRT_LPI2C_DMA_MAXMSG
+	int "Maximum number messages that will be DMAed"
+	default 8
+	depends on IMXRT_LPI2C_DMA
+	---help---
+		This option set the mumber of mesg that can be in a transfer.
+		It is used to allocate space for the 16 bit LPI2C commands
+		that will be DMA-ed to the LPI2C device.
+
 config IMXRT_LPI2C_DYNTIMEO
 	bool "Use dynamic timeouts"
 	default n
diff --git a/arch/arm/src/imxrt/imxrt_lpi2c.c b/arch/arm/src/imxrt/imxrt_lpi2c.c
index d5537a080f..6310594139 100644
--- a/arch/arm/src/imxrt/imxrt_lpi2c.c
+++ b/arch/arm/src/imxrt/imxrt_lpi2c.c
@@ -44,8 +44,11 @@
 
 #include "arm_internal.h"
 #include "imxrt_lpi2c.h"
+#include "imxrt_edma.h"
 #include "imxrt_gpio.h"
+#include "imxrt_lpi2c.h"
 
+#include "hardware/imxrt_dmamux.h"
 #include "hardware/imxrt_pinmux.h"
 #include "hardware/imxrt_ccm.h"
 #include "imxrt_periphclks.h"
@@ -171,6 +174,9 @@ struct imxrt_lpi2c_config_s
 #ifndef CONFIG_I2C_POLLED
   uint32_t irq;               /* Event IRQ */
 #endif
+#ifdef CONFIG_IMXRT_LPI2C_DMA
+  uint32_t        dma_reqsrc;  /* DMA mux source */
+#endif
 };
 
 /* I2C Device Private Data */
@@ -211,6 +217,11 @@ struct imxrt_lpi2c_priv_s
 #endif
 
   uint32_t status;             /* End of transfer SR2|SR1 status */
+
+#ifdef CONFIG_IMXRT_LPI2C_DMA
+  DMACH_HANDLE    dma;                                  /* DMA handle */
+  uint16_t        cmnds[CONFIG_IMXRT_LPI2C_DMA_MAXMSG]; /* Commands */
+#endif
 };
 
 /****************************************************************************
@@ -278,6 +289,11 @@ static int imxrt_lpi2c_transfer(struct i2c_master_s *dev,
 static int imxrt_lpi2c_reset(struct i2c_master_s *dev);
 #endif
 
+#ifdef CONFIG_IMXRT_LPI2C_DMA
+static void imxrt_dma_callback(DMACH_HANDLE handle, void *arg, bool done,
+                                  int result);
+#endif
+
 /****************************************************************************
  * Private Data
  ****************************************************************************/
@@ -302,12 +318,18 @@ static const char *g_trace_names[] =
 
 static const struct i2c_ops_s imxrt_lpi2c_ops =
 {
-  .transfer = imxrt_lpi2c_transfer
+  .transfer = imxrt_lpi2c_transfer,
 #ifdef CONFIG_I2C_RESET
-  , .reset  = imxrt_lpi2c_reset
+  .reset  = imxrt_lpi2c_reset,
 #endif
 };
 
+#ifdef CONFIG_IMXRT_LPI2C_DMA
+/* Receive Data DMA Enable */
+
+static uint32_t g_lpi2c_mder_rdde = LPI2C_MDER_RDDE;
+#endif
+
 /* I2C device structures */
 
 #ifdef CONFIG_IMXRT_LPI2C1
@@ -331,6 +353,9 @@ static const struct imxrt_lpi2c_config_s imxrt_lpi2c1_config =
 #ifndef CONFIG_I2C_POLLED
   .irq           = IMXRT_IRQ_LPI2C1,
 #endif
+#ifdef CONFIG_LPI2C1_DMA
+  .dma_reqsrc    = IMXRT_DMACHAN_LPI2C1,
+#endif
 };
 
 static struct imxrt_lpi2c_priv_s imxrt_lpi2c1_priv =
@@ -369,6 +394,9 @@ static const struct imxrt_lpi2c_config_s imxrt_lpi2c2_config =
 #ifndef CONFIG_I2C_POLLED
   .irq           = IMXRT_IRQ_LPI2C2,
 #endif
+#ifdef CONFIG_LPI2C2_DMA
+  .dma_reqsrc    = IMXRT_DMACHAN_LPI2C2,
+#endif
 };
 
 static struct imxrt_lpi2c_priv_s imxrt_lpi2c2_priv =
@@ -407,6 +435,9 @@ static const struct imxrt_lpi2c_config_s imxrt_lpi2c3_config =
 #ifndef CONFIG_I2C_POLLED
   .irq           = IMXRT_IRQ_LPI2C3,
 #endif
+#ifdef CONFIG_LPI2C3_DMA
+  .dma_reqsrc    = IMXRT_DMACHAN_LPI2C3,
+#endif
 };
 
 static struct imxrt_lpi2c_priv_s imxrt_lpi2c3_priv =
@@ -445,6 +476,9 @@ static const struct imxrt_lpi2c_config_s imxrt_lpi2c4_config =
 #ifndef CONFIG_I2C_POLLED
   .irq           = IMXRT_IRQ_LPI2C4,
 #endif
+#ifdef CONFIG_LPI2C4_DMA
+  .dma_reqsrc    = IMXRT_DMACHAN_LPI2C4,
+#endif
 };
 
 static struct imxrt_lpi2c_priv_s imxrt_lpi2c4_priv =
@@ -587,30 +621,43 @@ imxrt_lpi2c_sem_waitdone(struct imxrt_lpi2c_priv_s *priv)
 
   flags = enter_critical_section();
 
-  /* Enable Interrupts when master mode */
-
-  if (priv->config->mode == LPI2C_MASTER)
+#ifdef CONFIG_IMXRT_LPI2C_DMA
+  if (priv->dma == NULL)
     {
-      if ((priv->flags & I2C_M_READ) != 0)
+#endif
+      /* Enable Interrupts when master mode */
+
+      if (priv->config->mode == LPI2C_MASTER)
         {
-          regval = LPI2C_MIER_TDIE | LPI2C_MIER_RDIE | LPI2C_MIER_NDIE | \
-                   LPI2C_MIER_ALIE | LPI2C_MIER_SDIE;
-          imxrt_lpi2c_putreg(priv, IMXRT_LPI2C_MIER_OFFSET, regval);
+          if ((priv->flags & I2C_M_READ) != 0)
+            {
+              regval = LPI2C_MIER_TDIE | LPI2C_MIER_RDIE |
+                       LPI2C_MIER_NDIE | LPI2C_MIER_ALIE |
+                       LPI2C_MIER_SDIE;
+              imxrt_lpi2c_putreg(priv, IMXRT_LPI2C_MIER_OFFSET, regval);
+            }
+          else
+            {
+              regval = LPI2C_MIER_TDIE | LPI2C_MIER_NDIE | \
+                       LPI2C_MIER_ALIE | LPI2C_MIER_SDIE;
+              imxrt_lpi2c_putreg(priv, IMXRT_LPI2C_MIER_OFFSET, regval);
+            }
         }
+
+      /* Enable Interrupts when slave mode */
+
       else
         {
-          regval = LPI2C_MIER_TDIE | LPI2C_MIER_NDIE | \
-                   LPI2C_MIER_ALIE | LPI2C_MIER_SDIE;
-          imxrt_lpi2c_putreg(priv, IMXRT_LPI2C_MIER_OFFSET, regval);
+    #warning Missing logic for I2C Slave mode
         }
-    }
-
-  /* Enable Interrupts when slave mode */
 
-  else
-    {
-#warning Missing logic for I2C Slave mode
+      /* Signal the interrupt handler that we are waiting.  NOTE:  Interrupts
+       * are currently disabled but will be temporarily re-enabled below when
+       * nxsem_timedwait() sleeps.
+       */
+#ifdef CONFIG_IMXRT_LPI2C_DMA
     }
+#endif
 
   /* Signal the interrupt handler that we are waiting.  NOTE:  Interrupts
    * are currently disabled but will be temporarily re-enabled below when
@@ -861,6 +908,59 @@ imxrt_lpi2c_sem_destroy(struct imxrt_lpi2c_priv_s *priv)
 #endif
 }
 
+/****************************************************************************
+ * Name: imxrt_dma_callback
+ *
+ * Description:
+ *   This function performs the next I2C operation
+ *
+ ****************************************************************************/
+#ifdef CONFIG_IMXRT_LPI2C_DMA
+static void imxrt_dma_callback(DMACH_HANDLE handle, void *arg, bool done,
+                              int result)
+{
+  struct imxrt_lpi2c_priv_s *priv = (struct imxrt_lpi2c_priv_s *)arg;
+
+  imxrt_lpi2c_modifyreg(priv, IMXRT_LPI2C_MIER_OFFSET, 0,
+                              LPI2C_MIER_SDIE);
+
+  if (result != OK)
+    {
+      priv->status = imxrt_lpi2c_getstatus(priv);
+
+      if ((priv->status & LPI2C_MSR_ERROR_MASK) != 0)
+        {
+          i2cerr("ERROR: MSR: status: 0x0%" PRIx32 "\n", priv->status);
+
+          imxrt_lpi2c_traceevent(priv, I2CEVENT_ERROR, 0);
+
+          /* Clear the TX and RX FIFOs */
+
+          imxrt_lpi2c_modifyreg(priv, IMXRT_LPI2C_MCR_OFFSET, 0,
+                                LPI2C_MCR_RTF | LPI2C_MCR_RRF);
+
+          /* Clear the error */
+
+          imxrt_lpi2c_putreg(priv, IMXRT_LPI2C_MSR_OFFSET,
+                             (priv->status & (LPI2C_MSR_NDF |
+                                              LPI2C_MSR_ALF |
+                                              LPI2C_MSR_FEF |
+                                              LPI2C_MSR_PLTF)));
+
+          if (priv->intstate == INTSTATE_WAITING)
+            {
+              /* inform the thread that transfer is complete
+               * and wake it up
+               */
+
+              priv->intstate = INTSTATE_DONE;
+              nxsem_post(&priv->sem_isr);
+            }
+        }
+    }
+}
+#endif
+
 /****************************************************************************
  * Name: imxrt_lpi2c_trace*
  *
@@ -1217,6 +1317,20 @@ imxrt_lpi2c_getstatus(struct imxrt_lpi2c_priv_s *priv)
   return imxrt_lpi2c_getreg(priv, IMXRT_LPI2C_MSR_OFFSET);
 }
 
+/****************************************************************************
+ * Name: imxrt_lpi2c_getenabledints
+ *
+ * Description:
+ *   Get 32-bit status
+ *
+ ****************************************************************************/
+
+static inline uint32_t
+imxrt_lpi2c_getenabledints(FAR struct imxrt_lpi2c_priv_s *priv)
+{
+  return imxrt_lpi2c_getreg(priv, IMXRT_LPI2C_MIER_OFFSET);
+}
+
 /****************************************************************************
  * Name: imxrt_lpi2c_isr_process
  *
@@ -1229,6 +1343,79 @@ static int imxrt_lpi2c_isr_process(struct imxrt_lpi2c_priv_s *priv)
 {
   uint32_t status = imxrt_lpi2c_getstatus(priv);
 
+#ifdef CONFIG_IMXRT_LPI2C_DMA
+  uint32_t current_status = status;
+
+  /* Condition the status with only the enabled interrupts */
+
+  status &= imxrt_lpi2c_getenabledints(priv);
+
+  if (priv->dma != NULL)
+    {
+      /* End of packet or Stop */
+
+      if ((status & (LPI2C_MSR_SDF | LPI2C_MSR_EPF)) != 0)
+        {
+          imxrt_lpi2c_traceevent(priv, I2CEVENT_STOP, 0);
+
+          /* Acknowledge End of packet or Stop */
+
+          imxrt_lpi2c_putreg(priv, IMXRT_LPI2C_MSR_OFFSET, status &
+                                                           (LPI2C_MSR_SDF |
+                                                           LPI2C_MSR_EPF));
+        }
+
+      /* Is there an Error condition */
+
+      if (current_status & LPI2C_MSR_ERROR_MASK)
+        {
+          imxrt_lpi2c_traceevent(priv, I2CEVENT_ERROR, 0);
+
+          /* Shutdown DMA */
+
+          imxrt_dmach_stop(priv->dma);
+
+          /* Clear the TX and RX FIFOs */
+
+          imxrt_lpi2c_modifyreg(priv, IMXRT_LPI2C_MCR_OFFSET, 0,
+                                LPI2C_MCR_RTF | LPI2C_MCR_RRF);
+
+          /* Clear the error */
+
+          imxrt_lpi2c_putreg(priv, IMXRT_LPI2C_MSR_OFFSET,
+                            (current_status & (LPI2C_MSR_NDF |
+                                               LPI2C_MSR_ALF |
+                                               LPI2C_MSR_FEF)));
+
+          /* Return the full error status */
+
+          status = current_status;
+        }
+
+      /* Mark that this transaction stopped */
+
+      priv->msgv = NULL;
+      priv->msgc = 0;
+      priv->dcnt = -1;
+
+      if (priv->intstate == INTSTATE_WAITING)
+        {
+          /* Update Status once at the end */
+
+          priv->status = status;
+
+          /* inform the thread that transfer is complete
+           * and wake it up
+           */
+
+          priv->intstate = INTSTATE_DONE;
+          nxsem_post(&priv->sem_isr);
+        }
+
+      return OK;
+    }
+
+#endif
   /* Check for new trace setup */
 
   imxrt_lpi2c_tracenew(priv, status);
@@ -1369,8 +1556,8 @@ static int imxrt_lpi2c_isr_process(struct imxrt_lpi2c_priv_s *priv)
                * and wake it up
                */
 
-              nxsem_post(&priv->sem_isr);
               priv->intstate = INTSTATE_DONE;
+              nxsem_post(&priv->sem_isr);
             }
 #else
           priv->status = status;
@@ -1412,22 +1599,22 @@ static int imxrt_lpi2c_isr_process(struct imxrt_lpi2c_priv_s *priv)
                                     LPI2C_MSR_FEF)));
 
 #ifndef CONFIG_I2C_POLLED
-          if (priv->intstate == INTSTATE_WAITING)
-            {
-              /* Update Status once at the end */
+      if (priv->intstate == INTSTATE_WAITING)
+        {
+          /* Update Status once at the end */
 
-              priv->status = status;
+          priv->status = status;
 
-              /* inform the thread that transfer is complete
-               * and wake it up
-               */
+          /* inform the thread that transfer is complete
+           * and wake it up
+           */
 
-              nxsem_post(&priv->sem_isr);
-              priv->intstate = INTSTATE_DONE;
-            }
-#else
-          priv->status = status;
           priv->intstate = INTSTATE_DONE;
+          nxsem_post(&priv->sem_isr);
+        }
+#else
+      priv->status = status;
+      priv->intstate = INTSTATE_DONE;
 #endif
     }
 
@@ -1448,7 +1635,8 @@ static int imxrt_lpi2c_isr(int irq, void *context, void *arg)
   struct imxrt_lpi2c_priv_s *priv = (struct imxrt_lpi2c_priv_s *)arg;
 
   DEBUGASSERT(priv != NULL);
-  return imxrt_lpi2c_isr_process(priv);
+  int rv = imxrt_lpi2c_isr_process(priv);
+  return rv;
 }
 #endif
 
@@ -1547,7 +1735,7 @@ static int imxrt_lpi2c_init(struct imxrt_lpi2c_priv_s *priv)
   /* Pin config and ignore NACK disable */
 
   imxrt_lpi2c_modifyreg(priv, IMXRT_LPI2C_MCFGR1_OFFSET,
-                        LPI2C_MCFGR1_IGNACK | LPI2C_MCFGR1_PINCFG_MASK, 0);
+                        LPI2C_MCFGR1_IGNACK, LPI2C_MCFGR1_AUTOSTOP);
 
   /* Set tx and rx watermarks */
 
@@ -1621,6 +1809,260 @@ static int imxrt_lpi2c_deinit(struct imxrt_lpi2c_priv_s *priv)
  * Device Driver Operations
  ****************************************************************************/
 
+/****************************************************************************
+ * Name: imxrt_lpi2c_dma_configure
+ *
+ * Description:
+ *   Create a TCD to change from TX to RX
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_IMXRT_LPI2C_DMA
+static int imxrt_lpi2c_dma_configure_mder(FAR struct imxrt_lpi2c_priv_s *
+                                          priv)
+{
+  struct imxrt_edma_xfrconfig_s config;
+  memset(&config, 0, sizeof(config));
+
+  config.saddr  = (uint32_t) &g_lpi2c_mder_rdde;
+  config.daddr  = priv->config->base + IMXRT_LPI2C_MDER_OFFSET;
+  config.soff   = 0;
+  config.doff   = sizeof(uint8_t);
+  config.iter   = 1;
+  config.flags  = EDMA_CONFIG_LINKTYPE_LINKNONE;
+  config.ssize  = EDMA_8BIT;
+  config.dsize  = EDMA_8BIT;
+  config.nbytes = sizeof(uint8_t);
+
+  up_clean_dcache((uintptr_t)config.saddr ,
+                       (uintptr_t)config.saddr + config.nbytes);
+
+  return imxrt_dmach_xfrsetup(priv->dma, &config);
+}
+#endif
+
+/****************************************************************************
+ * Name: imxrt_lpi2c_dma_command_configure
+ *
+ * Description:
+ *   Create a command TCD
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_IMXRT_LPI2C_DMA
+static int imxrt_lpi2c_dma_command_configure(FAR struct imxrt_lpi2c_priv_s
+                                              *priv, uint16_t *ccmd,
+                                              uint32_t ncmd)
+{
+  struct imxrt_edma_xfrconfig_s config;
+  memset(&config, 0, sizeof(config));
+
+  config.saddr  = (uint32_t) ccmd;
+  config.daddr  = priv->config->base + IMXRT_LPI2C_MTDR_OFFSET;
+  config.soff   = sizeof(uint16_t);
+  config.doff   = 0;
+  config.iter   = 1;
+  config.flags  = EDMA_CONFIG_LINKTYPE_LINKNONE;
+  config.ssize  = EDMA_16BIT;
+  config.dsize  = EDMA_16BIT;
+  config.nbytes = sizeof(uint16_t) * ncmd;
+
+  up_clean_dcache((uintptr_t)config.saddr ,
+                       (uintptr_t)config.saddr + config.nbytes);
+
+  return imxrt_dmach_xfrsetup(priv->dma, &config);
+}
+#endif
+
+/****************************************************************************
+ * Name: imxrt_lpi2c_dma_data_configure
+ *
+ * Description:
+ *   Create a data TCD
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_IMXRT_LPI2C_DMA
+static int imxrt_lpi2c_dma_data_configure(FAR struct imxrt_lpi2c_priv_s
+                                              *priv,
+                                              struct i2c_msg_s *msg)
+{
+  struct imxrt_edma_xfrconfig_s config;
+  memset(&config, 0, sizeof(config));
+
+  config.iter   = msg->length;
+  config.flags  = EDMA_CONFIG_LINKTYPE_LINKNONE;
+  config.ssize  = EDMA_8BIT;
+  config.dsize  = EDMA_8BIT;
+  config.nbytes = sizeof(msg->buffer[0]);
+
+  if (msg->flags & I2C_M_READ)
+    {
+      config.saddr  = priv->config->base + IMXRT_LPI2C_MRDR_OFFSET;
+      config.daddr  = (uint32_t) msg->buffer;
+      config.soff   = 0;
+      config.doff   = sizeof(msg->buffer[0]);
+      up_invalidate_dcache((uintptr_t)msg->buffer,
+                           (uintptr_t)msg->buffer + msg->length);
+    }
+  else
+    {
+      config.saddr  = (uint32_t) msg->buffer;
+      config.daddr  = priv->config->base + IMXRT_LPI2C_MTDR_OFFSET;
+      config.soff   = sizeof(msg->buffer[0]);
+      config.doff   = 0;
+      up_clean_dcache((uintptr_t)msg->buffer,
+                      (uintptr_t)msg->buffer + msg->length);
+    }
+
+  return imxrt_dmach_xfrsetup(priv->dma, &config) ? 0 : msg->length;
+}
+#endif
+
+/****************************************************************************
+ * Name: imxrt_lpi2c_configure_dma_transfer
+ *
+ * Description:
+ *   DMA based I2C transfer function
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_IMXRT_LPI2C_DMA
+static int imxrt_lpi2c_form_command_list(FAR struct imxrt_lpi2c_priv_s
+                                              *priv, struct i2c_msg_s *msg,
+                                              int ncmds)
+{
+  ssize_t length = 0;
+
+  if (priv->flags & I2C_M_NOSTART)
+    {
+      if (priv->flags & I2C_M_READ)
+        {
+          /* No start read operation */
+
+          priv->cmnds[ncmds++] = LPI2C_MTDR_CMD_RXD |
+                                 LPI2C_MTDR_DATA(msg->length - 1);
+        }
+    }
+  else
+    {
+      /* A start based read or write operation */
+
+      /* Create bus address with R/W */
+
+      uint16_t badd = (priv->flags & I2C_M_READ) ? I2C_READADDR8(msg->addr) :
+                                                   I2C_WRITEADDR8(msg->addr);
+
+      priv->cmnds[ncmds++] = LPI2C_MTDR_CMD_START | LPI2C_MTDR_DATA(badd);
+
+      if (badd & I2C_READBIT)
+        {
+          length =  msg->length;
+          while (length)
+            {
+              if (length > 256u)
+                {
+                  priv->cmnds[ncmds++] = LPI2C_MTDR_CMD_RXD |
+                                         LPI2C_MTDR_DATA(256u - 1);
+                  length -= 256u;
+                }
+              else
+                {
+                  priv->cmnds[ncmds++] = LPI2C_MTDR_CMD_RXD |
+                                         LPI2C_MTDR_DATA(length - 1);
+                  length = 0;
+                }
+            }
+        }
+    }
+
+  return ncmds;
+}
+#endif
+
+/****************************************************************************
+ * Name: imxrt_lpi2c_dma_transfer
+ *
+ * Description:
+ *   DMA based I2C transfer function
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_IMXRT_LPI2C_DMA
+static int imxrt_lpi2c_dma_transfer(FAR struct imxrt_lpi2c_priv_s *priv)
+{
+  int m;
+  int ntotcmds = 0;
+  int ncmds = 0;
+  uint16_t *ccmnd = NULL;
+
+  /* Disable Interrupts */
+
+  imxrt_lpi2c_modifyreg(priv, IMXRT_LPI2C_MIER_OFFSET,
+                            LPI2C_MIER_RDIE | LPI2C_MIER_TDIE, 0);
+
+  /* Disable DMA */
+
+  imxrt_lpi2c_modifyreg(priv, IMXRT_LPI2C_MDER_OFFSET, LPI2C_MDER_TDDE |
+                                                       LPI2C_MDER_RDDE, 0);
+
+  /* Turn off auto_stop option */
+
+  imxrt_lpi2c_modifyreg(priv, IMXRT_LPI2C_MCFGR1_OFFSET, 0,
+                        LPI2C_MCFGR1_IGNACK | LPI2C_MCFGR1_AUTOSTOP);
+
+  /* Form chains of tcd to process the messages */
+
+  for (m = 0; m < priv->msgc; m++)
+    {
+      ncmds = 0;
+      priv->flags = priv->msgv[m].flags;
+
+      /* Form a command list */
+
+      ccmnd = &priv->cmnds[ntotcmds];
+
+      ncmds = imxrt_lpi2c_form_command_list(priv, &priv->msgv[m], ntotcmds);
+
+      /* Have commands for this message ? */
+
+      if (ncmds != 0)
+        {
+          /* Build up a TCD with the command from this message */
+
+          imxrt_lpi2c_dma_command_configure(priv, ccmnd, ncmds - ntotcmds);
+
+          ntotcmds += ncmds;
+
+          DEBUGASSERT(ntotcmds < CONFIG_IMXRT_LPI2C_DMA_MAXMSG);
+
+          if (priv->flags & I2C_M_READ)
+            {
+              /* We have commands and this message is a read.
+               * Since there is only one DMA request line for both TX/RX
+               * we must insert a DMA operation to switch to the LSI2C from
+               * TX to RX DMA
+               */
+
+              imxrt_lpi2c_dma_configure_mder(priv);
+            }
+
+          imxrt_lpi2c_dma_data_configure(priv, &priv->msgv[m]);
+        }
+    }
+
+  imxrt_lpi2c_putreg(priv, IMXRT_LPI2C_MIER_OFFSET,
+                     LPI2C_MIER_NDIE | LPI2C_MIER_ALIE |
+                     LPI2C_MIER_PLTIE | LPI2C_MIER_FEIE);
+
+  imxrt_dmach_start(priv->dma, imxrt_dma_callback, (void *)priv);
+
+  imxrt_lpi2c_modifyreg(priv, IMXRT_LPI2C_MDER_OFFSET, 0,
+                          LPI2C_MDER_TDDE | LPI2C_MDER_RDDE);
+  return OK;
+}
+#endif
+
 /****************************************************************************
  * Name: imxrt_lpi2c_transfer
  *
@@ -1678,11 +2120,26 @@ static int imxrt_lpi2c_transfer(struct i2c_master_s *dev,
    * the BUSY flag.
    */
 
+#ifdef CONFIG_IMXRT_LPI2C_DMA
+  if (priv->dma)
+    {
+      imxrt_lpi2c_dma_transfer(priv);
+    }
+#endif
+
   if (imxrt_lpi2c_sem_waitdone(priv) < 0)
     {
+#ifdef CONFIG_IMXRT_LPI2C_DMA
+  if (priv->dma)
+    {
+      imxrt_dmach_stop(priv->dma);
+    }
+
+#endif
       ret = -ETIMEDOUT;
 
-      i2cerr("ERROR: Timed out: MCR: status: 0x%" PRIx32 "\n", priv->status);
+      i2cerr("ERROR: Timed out: MSR: status: 0x0%" PRIx32 "\n",
+             priv->status);
     }
 
   /* Check for error status conditions */
@@ -1920,6 +2377,15 @@ struct i2c_master_s *imxrt_i2cbus_initialize(int port)
     {
       imxrt_lpi2c_sem_init(priv);
       imxrt_lpi2c_init(priv);
+
+#ifdef CONFIG_IMXRT_LPI2C_DMA
+      if (priv->config->dma_reqsrc != 0)
+        {
+          priv->dma = imxrt_dmach_alloc(priv->config->dma_reqsrc |
+                                        DMAMUX_CHCFG_ENBL, 0);
+          DEBUGASSERT(priv->dma != NULL);
+        }
+#endif
     }
 
   leave_critical_section(flags);
@@ -1961,6 +2427,15 @@ int imxrt_i2cbus_uninitialize(struct i2c_master_s *dev)
 
   /* Disable power and other HW resource (GPIO's) */
 
+#ifdef CONFIG_IMXRT_LPI2C_DMA
+  if (priv->dma != NULL)
+    {
+      imxrt_dmach_stop(priv->dma);
+      imxrt_dmach_free(priv->dma);
+      priv->dma = NULL;
+    }
+#endif
+
   imxrt_lpi2c_deinit(priv);
 
   /* Release unused resources */


[incubator-nuttx] 03/04: imxrt:serial add TX & RX DMA support

Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit fa58381e58846362e22de0f7a5384ec84315c899
Author: David Sidrane <Da...@NscDg.com>
AuthorDate: Thu Jun 9 13:31:43 2022 -0700

    imxrt:serial add TX & RX DMA support
    
    imxrt:serial ioctl should call to proper setup
---
 arch/arm/src/imxrt/imxrt_serial.c | 1798 ++++++++++++++++++++++++++++++-------
 arch/arm/src/imxrt/imxrt_serial.h |  184 ++++
 2 files changed, 1656 insertions(+), 326 deletions(-)

diff --git a/arch/arm/src/imxrt/imxrt_serial.c b/arch/arm/src/imxrt/imxrt_serial.c
index a3eba38136..5c650737cf 100644
--- a/arch/arm/src/imxrt/imxrt_serial.c
+++ b/arch/arm/src/imxrt/imxrt_serial.c
@@ -51,15 +51,136 @@
 #include "arm_internal.h"
 #include "hardware/imxrt_lpuart.h"
 #include "imxrt_gpio.h"
+#include "imxrt_edma.h"
+#include "hardware/imxrt_dmamux.h"
 #include "hardware/imxrt_pinmux.h"
 #include "imxrt_config.h"
 #include "imxrt_lowputc.h"
+#include "imxrt_serial.h"
 
 #ifdef USE_SERIALDRIVER
 
-/****************************************************************************
- * Pre-processor Definitions
- ****************************************************************************/
+/* The DMA buffer size when using RX DMA to emulate a FIFO.
+ *
+ * When streaming data, the generic serial layer will be called every time
+ * the FIFO receives half this number of bytes.
+ *
+ * This buffer size should be an even multiple of the Cortex-M7 D-Cache line
+ * size, ARMV7M_DCACHE_LINESIZE, so that it can be individually invalidated.
+ *
+ * Should there be a Cortex-M7 without a D-Cache, ARMV7M_DCACHE_LINESIZE
+ * would be zero!
+ */
+
+#  if !defined(ARMV7M_DCACHE_LINESIZE) || ARMV7M_DCACHE_LINESIZE == 0
+#    undef ARMV7M_DCACHE_LINESIZE
+#    define ARMV7M_DCACHE_LINESIZE 32
+#  endif
+
+#  if !defined(CONFIG_IMXRT_SERIAL_RXDMA_BUFFER_SIZE) || \
+      (CONFIG_IMXRT_SERIAL_RXDMA_BUFFER_SIZE < ARMV7M_DCACHE_LINESIZE)
+#    undef CONFIG_IMXRT_SERIAL_RXDMA_BUFFER_SIZE
+#    define CONFIG_IMXRT_SERIAL_RXDMA_BUFFER_SIZE ARMV7M_DCACHE_LINESIZE
+#  endif
+
+#  define RXDMA_BUFFER_MASK   (ARMV7M_DCACHE_LINESIZE - 1)
+#  define RXDMA_BUFFER_SIZE   ((CONFIG_IMXRT_SERIAL_RXDMA_BUFFER_SIZE \
+                                + RXDMA_BUFFER_MASK) & ~RXDMA_BUFFER_MASK)
+
+/* The DMA buffer size when using TX DMA.
+ *
+ * This TX buffer size should be an even multiple of the Cortex-M7 D-Cache
+ * line size, ARMV7M_DCACHE_LINESIZE, so that it can be individually
+ * invalidated.
+ *
+ * Should there be a Cortex-M7 without a D-Cache, ARMV7M_DCACHE_LINESIZE
+ * would be zero!
+ */
+
+#if !defined(ARMV7M_DCACHE_LINESIZE) || ARMV7M_DCACHE_LINESIZE == 0
+#  undef ARMV7M_DCACHE_LINESIZE
+#  define ARMV7M_DCACHE_LINESIZE 32
+#endif
+
+#define TXDMA_BUFFER_MASK   (ARMV7M_DCACHE_LINESIZE - 1)
+#define TXDMA_BUFFER_SIZE   ((CONFIG_IMXRT_SERIAL_RXDMA_BUFFER_SIZE \
+                              + RXDMA_BUFFER_MASK) & ~RXDMA_BUFFER_MASK)
+
+/* If built with CONFIG_ARMV7M_DCACHE Buffers need to be aligned and
+ * multiples of ARMV7M_DCACHE_LINESIZE
+ */
+
+#if defined(CONFIG_ARMV7M_DCACHE)
+#  define TXDMA_BUF_SIZE(b) (((b) + TXDMA_BUFFER_MASK) & ~TXDMA_BUFFER_MASK)
+#  define TXDMA_BUF_ALIGN   aligned_data(ARMV7M_DCACHE_LINESIZE);
+#else
+#  define TXDMA_BUF_SIZE(b)  (b)
+#  define TXDMA_BUF_ALIGN
+#endif
+
+#if !defined(CONFIG_LPUART1_TXDMA)
+#  define LPUART1_TXBUFSIZE_ADJUSTED  CONFIG_LPUART1_TXBUFSIZE
+#  define LPUART1_TXBUFSIZE_ALGN
+#else
+#  define LPUART1_TXBUFSIZE_ADJUSTED TXDMA_BUF_SIZE(CONFIG_LPUART1_TXBUFSIZE)
+#  define LPUART1_TXBUFSIZE_ALGN TXDMA_BUF_ALIGN
+#endif
+
+#if !defined(CONFIG_LPUART2_TXDMA)
+#  define LPUART2_TXBUFSIZE_ADJUSTED  CONFIG_LPUART2_TXBUFSIZE
+#  define LPUART2_TXBUFSIZE_ALGN
+#else
+#  define LPUART2_TXBUFSIZE_ADJUSTED TXDMA_BUF_SIZE(CONFIG_LPUART2_TXBUFSIZE)
+#  define LPUART2_TXBUFSIZE_ALGN TXDMA_BUF_ALIGN
+#endif
+
+#if !defined(CONFIG_LPUART3_TXDMA)
+#  define LPUART3_TXBUFSIZE_ADJUSTED  CONFIG_LPUART3_TXBUFSIZE
+#  define LPUART3_TXBUFSIZE_ALGN
+#else
+#  define LPUART3_TXBUFSIZE_ADJUSTED TXDMA_BUF_SIZE(CONFIG_LPUART3_TXBUFSIZE)
+#  define LPUART3_TXBUFSIZE_ALGN TXDMA_BUF_ALIGN
+#endif
+
+#if !defined(CONFIG_LPUART4_TXDMA)
+#  define LPUART4_TXBUFSIZE_ADJUSTED  CONFIG_LPUART4_TXBUFSIZE
+#  define LPUART4_TXBUFSIZE_ALGN
+#else
+#  define LPUART4_TXBUFSIZE_ADJUSTED TXDMA_BUF_SIZE(CONFIG_LPUART4_TXBUFSIZE)
+#  define LPUART4_TXBUFSIZE_ALGN TXDMA_BUF_ALIGN
+#endif
+
+#if !defined(CONFIG_LPUART5_TXDMA)
+#  define LPUART5_TXBUFSIZE_ADJUSTED  CONFIG_LPUART5_TXBUFSIZE
+#  define LPUART5_TXBUFSIZE_ALGN
+#else
+#  define LPUART5_TXBUFSIZE_ADJUSTED TXDMA_BUF_SIZE(CONFIG_LPUART5_TXBUFSIZE)
+#  define LPUART5_TXBUFSIZE_ALGN TXDMA_BUF_ALIGN
+#endif
+
+#if !defined(CONFIG_LPUART6_TXDMA)
+#  define LPUART6_TXBUFSIZE_ADJUSTED  CONFIG_LPUART6_TXBUFSIZE
+#  define LPUART6_TXBUFSIZE_ALGN
+#else
+#  define LPUART6_TXBUFSIZE_ADJUSTED TXDMA_BUF_SIZE(CONFIG_LPUART6_TXBUFSIZE)
+#  define LPUART6_TXBUFSIZE_ALGN TXDMA_BUF_ALIGN
+#endif
+
+#if !defined(CONFIG_LPUART7_TXDMA)
+#  define LPUART7_TXBUFSIZE_ADJUSTED  CONFIG_LPUART7_TXBUFSIZE
+#  define LPUART7_TXBUFSIZE_ALGN
+#else
+#  define LPUART7_TXBUFSIZE_ADJUSTED TXDMA_BUF_SIZE(CONFIG_LPUART7_TXBUFSIZE)
+#  define LPUART7_TXBUFSIZE_ALGN TXDMA_BUF_ALIGN
+#endif
+
+#if !defined(CONFIG_LPUART8_TXDMA)
+#  define LPUART8_TXBUFSIZE_ADJUSTED  CONFIG_LPUART8_TXBUFSIZE
+#  define LPUART8_TXBUFSIZE_ALGN
+#else
+#  define LPUART8_TXBUFSIZE_ADJUSTED TXDMA_BUF_SIZE(CONFIG_LPUART8_TXBUFSIZE)
+#  define LPUART8_TXBUFSIZE_ALGN TXDMA_BUF_ALIGN
+#endif
 
 /* Which LPUART with be tty0/console and which tty1-7?  The console will
  * always be ttyS0.  If there is no console then will use the lowest
@@ -69,95 +190,147 @@
 /* First pick the console and ttys0.  This could be any of LPUART1-8 */
 
 #if defined(CONFIG_LPUART1_SERIAL_CONSOLE)
-#  define CONSOLE_DEV         g_uart1port /* LPUART1 is console */
-#  define TTYS0_DEV           g_uart1port /* LPUART1 is ttyS0 */
-#  define UART1_ASSIGNED      1
+#  define CONSOLE_DEV         g_lpuart1priv /* LPUART1 is console */
+#  define TTYS0_DEV           g_lpuart1priv /* LPUART1 is ttyS0 */
+#  define LPUART1_ASSIGNED    1
+#  if defined(CONFIG_LPUART1_RXDMA)
+#    define SERIAL_HAVE_CONSOLE_RXDMA 1
+#  endif
+#  if defined(CONFIG_LPUART1_TXDMA)
+#    define SERIAL_HAVE_CONSOLE_TXDMA 1
+#  endif
 #elif defined(CONFIG_LPUART2_SERIAL_CONSOLE)
-#  define CONSOLE_DEV         g_uart2port /* LPUART2 is console */
-#  define TTYS0_DEV           g_uart2port /* LPUART2 is ttyS0 */
-#  define UART2_ASSIGNED      1
+#  define CONSOLE_DEV         g_lpuart2priv /* LPUART2 is console */
+#  define TTYS0_DEV           g_lpuart2priv /* LPUART2 is ttyS0 */
+#  define LPUART2_ASSIGNED    1
+#  if defined(CONFIG_LPUART2_RXDMA)
+#    define SERIAL_HAVE_CONSOLE_RXDMA 1
+#  endif
+#  if defined(CONFIG_LPUART2_TXDMA)
+#    define SERIAL_HAVE_CONSOLE_TXDMA 1
+#  endif
 #elif defined(CONFIG_LPUART3_SERIAL_CONSOLE)
-#  define CONSOLE_DEV         g_uart3port /* LPUART3 is console */
-#  define TTYS0_DEV           g_uart3port /* LPUART3 is ttyS0 */
-#  define UART3_ASSIGNED      1
+#  define CONSOLE_DEV         g_lpuart3priv /* LPUART3 is console */
+#  define TTYS0_DEV           g_lpuart3priv /* LPUART3 is ttyS0 */
+#  define LPUART3_ASSIGNED    1
+#  if defined(CONFIG_LPUART3_RXDMA)
+#    define SERIAL_HAVE_CONSOLE_RXDMA 1
+#  endif
+#  if defined(CONFIG_LPUART3_TXDMA)
+#    define SERIAL_HAVE_CONSOLE_TXDMA 1
+#  endif
 #elif defined(CONFIG_LPUART4_SERIAL_CONSOLE)
-#  define CONSOLE_DEV         g_uart4port /* LPUART4 is console */
-#  define TTYS0_DEV           g_uart4port /* LPUART4 is ttyS0 */
-#  define UART4_ASSIGNED      1
+#  define CONSOLE_DEV         g_lpuart4priv /* LPUART4 is console */
+#  define TTYS0_DEV           g_lpuart4priv /* LPUART4 is ttyS0 */
+#  define LPUART4_ASSIGNED    1
+#  if defined(CONFIG_LPUART4_RXDMA)
+#    define SERIAL_HAVE_CONSOLE_RXDMA 1
+#  endif
+#  if defined(CONFIG_LPUART4_TXDMA)
+#    define SERIAL_HAVE_CONSOLE_TXDMA 1
+#  endif
 #elif defined(CONFIG_LPUART5_SERIAL_CONSOLE)
-#  define CONSOLE_DEV         g_uart5port /* LPUART5 is console */
-#  define TTYS0_DEV           g_uart5port /* LPUART5 is ttyS0 */
-#  define UART5_ASSIGNED      1
+#  define CONSOLE_DEV         g_lpuart5priv /* LPUART5 is console */
+#  define TTYS0_DEV           g_lpuart5priv /* LPUART5 is ttyS0 */
+#  define LPUART5_ASSIGNED    1
+#  if defined(CONFIG_LPUART5_RXDMA)
+#    define SERIAL_HAVE_CONSOLE_RXDMA 1
+#  endif
+#  if defined(CONFIG_LPUART5_TXDMA)
+#    define SERIAL_HAVE_CONSOLE_TXDMA 1
+#  endif
 #elif defined(CONFIG_LPUART6_SERIAL_CONSOLE)
-#  define CONSOLE_DEV         g_uart6port /* LPUART6 is console */
-#  define TTYS0_DEV           g_uart6port /* LPUART6 is ttyS0 */
-#  define UART6_ASSIGNED      1
+#  define CONSOLE_DEV         g_lpuart6priv /* LPUART6 is console */
+#  define TTYS0_DEV           g_lpuart6priv /* LPUART6 is ttyS0 */
+#  define LPUART6_ASSIGNED    1
+#  if defined(CONFIG_LPUART6_RXDMA)
+#    define SERIAL_HAVE_CONSOLE_RXDMA 1
+#  endif
+#  if defined(CONFIG_LPUART6_TXDMA)
+#    define SERIAL_HAVE_CONSOLE_TXDMA 1
+#  endif
 #elif defined(CONFIG_LPUART7_SERIAL_CONSOLE)
-#  define CONSOLE_DEV         g_uart7port /* LPUART7 is console */
-#  define TTYS0_DEV           g_uart7port /* LPUART7 is ttyS0 */
-#  define UART7_ASSIGNED      1
+#  define CONSOLE_DEV         g_lpuart7priv /* LPUART7 is console */
+#  define TTYS0_DEV           g_lpuart7priv /* LPUART7 is ttyS0 */
+#  define LPUART7_ASSIGNED    1
+#  if defined(CONFIG_LPUART7_RXDMA)
+#    define SERIAL_HAVE_CONSOLE_RXDMA 1
+#  endif
+#  if defined(CONFIG_LPUART7_TXDMA)
+#    define SERIAL_HAVE_CONSOLE_TXDMA 1
+#  endif
 #elif defined(CONFIG_LPUART8_SERIAL_CONSOLE)
-#  define CONSOLE_DEV         g_uart8port /* LPUART8 is console */
-#  define TTYS0_DEV           g_uart8port /* LPUART8 is ttyS0 */
-#  define UART8_ASSIGNED      1
+#  define CONSOLE_DEV         g_lpuart8priv /* LPUART8 is console */
+#  define TTYS0_DEV           g_lpuart8priv /* LPUART8 is ttyS0 */
+#  define LPUART8_ASSIGNED    1
+#  if defined(CONFIG_LPUART8_RXDMA)
+#    define SERIAL_HAVE_CONSOLE_RXDMA 1
+#  endif
+#  if defined(CONFIG_LPUART9_TXDMA)
+#    define SERIAL_HAVE_CONSOLE_TXDMA 1
+#  endif
 #else
 #  undef CONSOLE_DEV                      /* No console */
 #  if defined(CONFIG_IMXRT_LPUART1)
-#    define TTYS0_DEV         g_uart1port /* LPUART1 is ttyS0 */
+#    define TTYS0_DEV         g_lpuart1priv /* LPUART1 is ttyS0 */
 #    define UART1_ASSIGNED    1
 #  elif defined(CONFIG_IMXRT_LPUART2)
-#    define TTYS0_DEV         g_uart2port /* LPUART2 is ttyS0 */
+#    define TTYS0_DEV         g_lpuart2priv /* LPUART2 is ttyS0 */
 #    define UART2_ASSIGNED    1
 #  elif defined(CONFIG_IMXRT_LPUART3)
-#    define TTYS0_DEV         g_uart3port /* LPUART3 is ttyS0 */
+#    define TTYS0_DEV         g_lpuart3priv /* LPUART3 is ttyS0 */
 #    define UART3_ASSIGNED    1
 #  elif defined(CONFIG_IMXRT_LPUART4)
-#    define TTYS0_DEV         g_uart4port /* LPUART4 is ttyS0 */
+#    define TTYS0_DEV         g_lpuart4priv /* LPUART4 is ttyS0 */
 #    define UART4_ASSIGNED    1
 #  elif defined(CONFIG_IMXRT_LPUART5)
-#    define TTYS0_DEV         g_uart5port /* LPUART5 is ttyS0 */
+#    define TTYS0_DEV         g_lpuart5priv /* LPUART5 is ttyS0 */
 #    define UART5_ASSIGNED    1
 #  elif defined(CONFIG_IMXRT_LPUART6)
-#    define TTYS0_DEV         g_uart6port /* LPUART6 is ttyS0 */
+#    define TTYS0_DEV         g_lpuart6priv /* LPUART6 is ttyS0 */
 #    define UART6_ASSIGNED    1
 #  elif defined(CONFIG_IMXRT_LPUART7)
-#    define TTYS0_DEV         g_uart7port /* LPUART7 is ttyS0 */
+#    define TTYS0_DEV         g_lpuart7priv /* LPUART7 is ttyS0 */
 #    define UART7_ASSIGNED    1
 #  elif defined(CONFIG_IMXRT_LPUART8)
-#    define TTYS0_DEV         g_uart8port /* LPUART8 is ttyS0 */
+#    define TTYS0_DEV         g_lpuart8priv /* LPUART8 is ttyS0 */
 #    define UART8_ASSIGNED    1
 #  endif
 #endif
 
+#if defined(SERIAL_HAVE_CONSOLE_RXDMA) || defined(SERIAL_HAVE_CONSOLE_TXDMA)
+#  define SERIAL_HAVE_CONSOLE_DMA
+#endif
+
 /* Pick ttys1.  This could be any of UART1-8 excluding the console UART.
  * One of UART1-8 could be the console; one of UART1-8 has already been
  * assigned to ttys0.
  */
 
-#if defined(CONFIG_IMXRT_LPUART1) && !defined(UART1_ASSIGNED)
-#  define TTYS1_DEV           g_uart1port /* LPUART1 is ttyS1 */
-#  define UART1_ASSIGNED      1
-#elif defined(CONFIG_IMXRT_LPUART2) && !defined(UART2_ASSIGNED)
-#  define TTYS1_DEV           g_uart2port /* LPUART2 is ttyS1 */
-#  define UART2_ASSIGNED      1
-#elif defined(CONFIG_IMXRT_LPUART3) && !defined(UART3_ASSIGNED)
-#  define TTYS1_DEV           g_uart3port /* LPUART3 is ttyS1 */
-#  define UART3_ASSIGNED      1
-#elif defined(CONFIG_IMXRT_LPUART4) && !defined(UART4_ASSIGNED)
-#  define TTYS1_DEV           g_uart4port /* LPUART4 is ttyS1 */
-#  define UART4_ASSIGNED      1
-#elif defined(CONFIG_IMXRT_LPUART5) && !defined(UART5_ASSIGNED)
-#  define TTYS1_DEV           g_uart5port /* LPUART5 is ttyS1 */
-#  define UART5_ASSIGNED      1
-#elif defined(CONFIG_IMXRT_LPUART6) && !defined(UART6_ASSIGNED)
-#  define TTYS1_DEV           g_uart6port /* LPUART6 is ttyS1 */
-#  define UART6_ASSIGNED      1
-#elif defined(CONFIG_IMXRT_LPUART7) && !defined(UART7_ASSIGNED)
-#  define TTYS1_DEV           g_uart7port /* LPUART7 is ttyS1 */
-#  define UART7_ASSIGNED      1
-#elif defined(CONFIG_IMXRT_LPUART8) && !defined(UART8_ASSIGNED)
-#  define TTYS1_DEV           g_uart8port /* LPUART8 is ttyS1 */
-#  define UART8_ASSIGNED      1
+#if defined(CONFIG_IMXRT_LPUART1) && !defined(LPUART1_ASSIGNED)
+#  define TTYS1_DEV           g_lpuart1priv /* LPUART1 is ttyS1 */
+#  define LPUART1_ASSIGNED    1
+#elif defined(CONFIG_IMXRT_LPUART2) && !defined(LPUART2_ASSIGNED)
+#  define TTYS1_DEV           g_lpuart2priv /* LPUART2 is ttyS1 */
+#  define LPUART2_ASSIGNED    1
+#elif defined(CONFIG_IMXRT_LPUART3) && !defined(LPUART3_ASSIGNED)
+#  define TTYS1_DEV           g_lpuart3priv /* LPUART3 is ttyS1 */
+#  define LPUART3_ASSIGNED    1
+#elif defined(CONFIG_IMXRT_LPUART4) && !defined(LPUART4_ASSIGNED)
+#  define TTYS1_DEV           g_lpuart4priv /* LPUART4 is ttyS1 */
+#  define LPUART4_ASSIGNED    1
+#elif defined(CONFIG_IMXRT_LPUART5) && !defined(LPUART5_ASSIGNED)
+#  define TTYS1_DEV           g_lpuart5priv /* LPUART5 is ttyS1 */
+#  define LPUART5_ASSIGNED    1
+#elif defined(CONFIG_IMXRT_LPUART6) && !defined(LPUART6_ASSIGNED)
+#  define TTYS1_DEV           g_lpuart6priv /* LPUART6 is ttyS1 */
+#  define LPUART6_ASSIGNED    1
+#elif defined(CONFIG_IMXRT_LPUART7) && !defined(LPUART7_ASSIGNED)
+#  define TTYS1_DEV           g_lpuart7priv /* LPUART7 is ttyS1 */
+#  define LPUART7_ASSIGNED    1
+#elif defined(CONFIG_IMXRT_LPUART8) && !defined(LPUART8_ASSIGNED)
+#  define TTYS1_DEV           g_lpuart8priv /* LPUART8 is ttyS1 */
+#  define LPUART8_ASSIGNED    1
 #endif
 
 /* Pick ttys2.  This could be one of UART2-8. It can't be UART1 because that
@@ -165,27 +338,27 @@
  * console.  One of UART2-8 has already been assigned to ttys0 or ttyS1.
  */
 
-#if defined(CONFIG_IMXRT_LPUART2) && !defined(UART2_ASSIGNED)
-#  define TTYS2_DEV           g_uart2port /* LPUART2 is ttyS2 */
-#  define UART2_ASSIGNED      1
-#elif defined(CONFIG_IMXRT_LPUART3) && !defined(UART3_ASSIGNED)
-#  define TTYS2_DEV           g_uart3port /* LPUART3 is ttyS2 */
-#  define UART3_ASSIGNED      1
-#elif defined(CONFIG_IMXRT_LPUART4) && !defined(UART4_ASSIGNED)
-#  define TTYS2_DEV           g_uart4port /* LPUART4 is ttyS2 */
-#  define UART4_ASSIGNED      1
-#elif defined(CONFIG_IMXRT_LPUART5) && !defined(UART5_ASSIGNED)
-#  define TTYS2_DEV           g_uart5port /* LPUART5 is ttyS2 */
-#  define UART5_ASSIGNED      1
-#elif defined(CONFIG_IMXRT_LPUART6) && !defined(UART6_ASSIGNED)
-#  define TTYS2_DEV           g_uart6port /* LPUART6 is ttyS2 */
-#  define UART6_ASSIGNED      1
-#elif defined(CONFIG_IMXRT_LPUART7) && !defined(UART7_ASSIGNED)
-#  define TTYS2_DEV           g_uart7port /* LPUART7 is ttyS2 */
-#  define UART7_ASSIGNED      1
-#elif defined(CONFIG_IMXRT_LPUART8) && !defined(UART8_ASSIGNED)
-#  define TTYS2_DEV           g_uart8port /* LPUART8 is ttyS2 */
-#  define UART8_ASSIGNED      1
+#if defined(CONFIG_IMXRT_LPUART2) && !defined(LPUART2_ASSIGNED)
+#  define TTYS2_DEV           g_lpuart2priv /* LPUART2 is ttyS2 */
+#  define LPUART2_ASSIGNED    1
+#elif defined(CONFIG_IMXRT_LPUART3) && !defined(LPUART3_ASSIGNED)
+#  define TTYS2_DEV           g_lpuart3priv /* LPUART3 is ttyS2 */
+#  define LPUART3_ASSIGNED    1
+#elif defined(CONFIG_IMXRT_LPUART4) && !defined(LPUART4_ASSIGNED)
+#  define TTYS2_DEV           g_lpuart4priv /* LPUART4 is ttyS2 */
+#  define LPUART4_ASSIGNED    1
+#elif defined(CONFIG_IMXRT_LPUART5) && !defined(LPUART5_ASSIGNED)
+#  define TTYS2_DEV           g_lpuart5priv /* LPUART5 is ttyS2 */
+#  define LPUART5_ASSIGNED    1
+#elif defined(CONFIG_IMXRT_LPUART6) && !defined(LPUART6_ASSIGNED)
+#  define TTYS2_DEV           g_lpuart6priv /* LPUART6 is ttyS2 */
+#  define LPUART6_ASSIGNED    1
+#elif defined(CONFIG_IMXRT_LPUART7) && !defined(LPUART7_ASSIGNED)
+#  define TTYS2_DEV           g_lpuart7priv /* LPUART7 is ttyS2 */
+#  define LPUART7_ASSIGNED    1
+#elif defined(CONFIG_IMXRT_LPUART8) && !defined(LPUART8_ASSIGNED)
+#  define TTYS2_DEV           g_lpuart8priv /* LPUART8 is ttyS2 */
+#  define LPUART8_ASSIGNED    1
 #endif
 
 /* Pick ttys3. This could be one of UART3-8. It can't be UART1-2 because
@@ -194,24 +367,24 @@
  * been assigned to ttys0, 1, or 3.
  */
 
-#if defined(CONFIG_IMXRT_LPUART3) && !defined(UART3_ASSIGNED)
-#  define TTYS3_DEV           g_uart3port /* LPUART3 is ttyS3 */
-#  define UART3_ASSIGNED      1
-#elif defined(CONFIG_IMXRT_LPUART4) && !defined(UART4_ASSIGNED)
-#  define TTYS3_DEV           g_uart4port /* LPUART4 is ttyS3 */
-#  define UART4_ASSIGNED      1
-#elif defined(CONFIG_IMXRT_LPUART5) && !defined(UART5_ASSIGNED)
-#  define TTYS3_DEV           g_uart5port /* LPUART5 is ttyS3 */
-#  define UART5_ASSIGNED      1
-#elif defined(CONFIG_IMXRT_LPUART6) && !defined(UART6_ASSIGNED)
-#  define TTYS3_DEV           g_uart6port /* LPUART6 is ttyS3 */
-#  define UART6_ASSIGNED      1
-#elif defined(CONFIG_IMXRT_LPUART7) && !defined(UART7_ASSIGNED)
-#  define TTYS3_DEV           g_uart7port /* LPUART7 is ttyS3 */
-#  define UART7_ASSIGNED      1
-#elif defined(CONFIG_IMXRT_LPUART8) && !defined(UART8_ASSIGNED)
-#  define TTYS3_DEV           g_uart8port /* LPUART8 is ttyS3 */
-#  define UART8_ASSIGNED      1
+#if defined(CONFIG_IMXRT_LPUART3) && !defined(LPUART3_ASSIGNED)
+#  define TTYS3_DEV           g_lpuart3priv /* LPUART3 is ttyS3 */
+#  define LPUART3_ASSIGNED    1
+#elif defined(CONFIG_IMXRT_LPUART4) && !defined(LPUART4_ASSIGNED)
+#  define TTYS3_DEV           g_lpuart4priv /* LPUART4 is ttyS3 */
+#  define LPUART4_ASSIGNED    1
+#elif defined(CONFIG_IMXRT_LPUART5) && !defined(LPUART5_ASSIGNED)
+#  define TTYS3_DEV           g_lpuart5priv /* LPUART5 is ttyS3 */
+#  define LPUART5_ASSIGNED    1
+#elif defined(CONFIG_IMXRT_LPUART6) && !defined(LPUART6_ASSIGNED)
+#  define TTYS3_DEV           g_lpuart6priv /* LPUART6 is ttyS3 */
+#  define LPUART6_ASSIGNED    1
+#elif defined(CONFIG_IMXRT_LPUART7) && !defined(LPUART7_ASSIGNED)
+#  define TTYS3_DEV           g_lpuart7priv /* LPUART7 is ttyS3 */
+#  define LPUART7_ASSIGNED    1
+#elif defined(CONFIG_IMXRT_LPUART8) && !defined(LPUART8_ASSIGNED)
+#  define TTYS3_DEV           g_lpuart8priv /* LPUART8 is ttyS3 */
+#  define LPUART8_ASSIGNED    1
 #endif
 
 /* Pick ttys4. This could be one of UART4-8. It can't be UART1-3 because
@@ -220,21 +393,21 @@
  * assigned to ttys0, 1, 3, or 4.
  */
 
-#if defined(CONFIG_IMXRT_LPUART4) && !defined(UART4_ASSIGNED)
-#  define TTYS4_DEV           g_uart4port /* LPUART4 is ttyS4 */
-#  define UART4_ASSIGNED      1
-#elif defined(CONFIG_IMXRT_LPUART5) && !defined(UART5_ASSIGNED)
-#  define TTYS4_DEV           g_uart5port /* LPUART5 is ttyS4 */
-#  define UART5_ASSIGNED      1
-#elif defined(CONFIG_IMXRT_LPUART6) && !defined(UART6_ASSIGNED)
-#  define TTYS4_DEV           g_uart6port /* LPUART6 is ttyS4 */
-#  define UART6_ASSIGNED      1
-#elif defined(CONFIG_IMXRT_LPUART7) && !defined(UART7_ASSIGNED)
-#  define TTYS4_DEV           g_uart7port /* LPUART7 is ttyS4 */
-#  define UART7_ASSIGNED      1
-#elif defined(CONFIG_IMXRT_LPUART8) && !defined(UART8_ASSIGNED)
-#  define TTYS4_DEV           g_uart8port /* LPUART8 is ttyS4 */
-#  define UART8_ASSIGNED      1
+#if defined(CONFIG_IMXRT_LPUART4) && !defined(LPUART4_ASSIGNED)
+#  define TTYS4_DEV           g_lpuart4priv /* LPUART4 is ttyS4 */
+#  define LPUART4_ASSIGNED    1
+#elif defined(CONFIG_IMXRT_LPUART5) && !defined(LPUART5_ASSIGNED)
+#  define TTYS4_DEV           g_lpuart5priv /* LPUART5 is ttyS4 */
+#  define LPUART5_ASSIGNED    1
+#elif defined(CONFIG_IMXRT_LPUART6) && !defined(LPUART6_ASSIGNED)
+#  define TTYS4_DEV           g_lpuart6priv /* LPUART6 is ttyS4 */
+#  define LPUART6_ASSIGNED    1
+#elif defined(CONFIG_IMXRT_LPUART7) && !defined(LPUART7_ASSIGNED)
+#  define TTYS4_DEV           g_lpuart7priv /* LPUART7 is ttyS4 */
+#  define LPUART7_ASSIGNED    1
+#elif defined(CONFIG_IMXRT_LPUART8) && !defined(LPUART8_ASSIGNED)
+#  define TTYS4_DEV           g_lpuart8priv /* LPUART8 is ttyS4 */
+#  define LPUART8_ASSIGNED    1
 #endif
 
 /* Pick ttys5. This could be one of UART5-8. It can't be UART1-4 because
@@ -243,18 +416,18 @@
  * assigned to ttys0, 1, 2, 3, or 4.
  */
 
-#if defined(CONFIG_IMXRT_LPUART5) && !defined(UART5_ASSIGNED)
-#  define TTYS5_DEV           g_uart5port /* LPUART5 is ttyS5 */
-#  define UART5_ASSIGNED      1
-#elif defined(CONFIG_IMXRT_LPUART6) && !defined(UART6_ASSIGNED)
-#  define TTYS5_DEV           g_uart6port /* LPUART6 is ttyS5 */
-#  define UART6_ASSIGNED      1
-#elif defined(CONFIG_IMXRT_LPUART7) && !defined(UART7_ASSIGNED)
-#  define TTYS5_DEV           g_uart7port /* LPUART7 is ttyS5 */
-#  define UART7_ASSIGNED      1
-#elif defined(CONFIG_IMXRT_LPUART8) && !defined(UART8_ASSIGNED)
-#  define TTYS5_DEV           g_uart8port /* LPUART8 is ttyS5 */
-#  define UART8_ASSIGNED      1
+#if defined(CONFIG_IMXRT_LPUART5) && !defined(LPUART5_ASSIGNED)
+#  define TTYS5_DEV           g_lpuart5priv /* LPUART5 is ttyS5 */
+#  define LPUART5_ASSIGNED    1
+#elif defined(CONFIG_IMXRT_LPUART6) && !defined(LPUART6_ASSIGNED)
+#  define TTYS5_DEV           g_lpuart6priv /* LPUART6 is ttyS5 */
+#  define LPUART6_ASSIGNED    1
+#elif defined(CONFIG_IMXRT_LPUART7) && !defined(LPUART7_ASSIGNED)
+#  define TTYS5_DEV           g_lpuart7priv /* LPUART7 is ttyS5 */
+#  define LPUART7_ASSIGNED    1
+#elif defined(CONFIG_IMXRT_LPUART8) && !defined(LPUART8_ASSIGNED)
+#  define TTYS5_DEV           g_lpuart8priv /* LPUART8 is ttyS5 */
+#  define LPUART8_ASSIGNED    1
 #endif
 
 /* Pick ttys6. This could be one of UART6-8. It can't be UART1-5 because
@@ -263,15 +436,15 @@
  * assigned to ttys0, 1, 2, 3, 4 or 5.
  */
 
-#if defined(CONFIG_IMXRT_LPUART6) && !defined(UART6_ASSIGNED)
-#  define TTYS6_DEV           g_uart6port /* LPUART6 is ttyS5 */
-#  define UART6_ASSIGNED      1
-#elif defined(CONFIG_IMXRT_LPUART7) && !defined(UART7_ASSIGNED)
-#  define TTYS6_DEV           g_uart7port /* LPUART7 is ttyS5 */
-#  define UART7_ASSIGNED      1
-#elif defined(CONFIG_IMXRT_LPUART8) && !defined(UART8_ASSIGNED)
-#  define TTYS6_DEV           g_uart8port /* LPUART8 is ttyS5 */
-#  define UART8_ASSIGNED      1
+#if defined(CONFIG_IMXRT_LPUART6) && !defined(LPUART6_ASSIGNED)
+#  define TTYS6_DEV           g_lpuart6priv /* LPUART6 is ttyS5 */
+#  define LPUART6_ASSIGNED    1
+#elif defined(CONFIG_IMXRT_LPUART7) && !defined(LPUART7_ASSIGNED)
+#  define TTYS6_DEV           g_lpuart7priv /* LPUART7 is ttyS5 */
+#  define LPUART7_ASSIGNED    1
+#elif defined(CONFIG_IMXRT_LPUART8) && !defined(LPUART8_ASSIGNED)
+#  define TTYS6_DEV           g_lpuart8priv /* LPUART8 is ttyS5 */
+#  define LPUART8_ASSIGNED    1
 #endif
 
 /* Pick ttys7. This could be one of UART7-8. It can't be UART1-6 because
@@ -280,12 +453,12 @@
  * assigned to ttys0, 1, 2, 3, 4, 5 or 6.
  */
 
-#if defined(CONFIG_IMXRT_LPUART7) && !defined(UART7_ASSIGNED)
-#  define TTYS7_DEV           g_uart7port /* LPUART7 is ttyS5 */
-#  define UART7_ASSIGNED      1
-#elif defined(CONFIG_IMXRT_LPUART8) && !defined(UART8_ASSIGNED)
-#  define TTYS7_DEV           g_uart8port /* LPUART8 is ttyS5 */
-#  define UART8_ASSIGNED      1
+#if defined(CONFIG_IMXRT_LPUART7) && !defined(LPUART7_ASSIGNED)
+#  define TTYS7_DEV           g_lpuart7priv /* LPUART7 is ttyS5 */
+#  define LPUART7_ASSIGNED    1
+#elif defined(CONFIG_IMXRT_LPUART8) && !defined(LPUART8_ASSIGNED)
+#  define TTYS7_DEV           g_lpuart8port /* LPUART8 is ttyS5 */
+#  define LPUART8_ASSIGNED    1
 #endif
 
 /* UART, if available, should have been assigned to ttyS0-7. */
@@ -302,6 +475,7 @@
 
 struct imxrt_uart_s
 {
+  struct uart_dev_s dev;    /* Generic UART device */
   uint32_t uartbase;        /* Base address of UART registers */
   uint32_t baud;            /* Configured baud */
   uint32_t ie;              /* Saved enabled interrupts */
@@ -310,10 +484,10 @@ struct imxrt_uart_s
   uint8_t  bits;            /* Number of bits (7 or 8) */
 #if defined(CONFIG_SERIAL_RS485CONTROL) || defined(CONFIG_SERIAL_IFLOWCONTROL)
   uint8_t  inviflow:1;      /* Invert RTS sense */
-  const uint32_t rts_gpio;  /* U[S]ART RTS GPIO pin configuration */
+  const uint32_t rts_gpio;  /* LPUART RTS GPIO pin configuration */
 #endif
 #ifdef CONFIG_SERIAL_OFLOWCONTROL
-  const uint32_t cts_gpio;  /* U[S]ART CTS GPIO pin configuration */
+  const uint32_t cts_gpio;  /* LPUART CTS GPIO pin configuration */
 #endif
 #ifdef CONFIG_IMXRT_LPUART_SINGLEWIRE
   const uint32_t tx_gpio;   /* TX GPIO pin configuration */
@@ -328,6 +502,23 @@ struct imxrt_uart_s
 #endif
 #ifdef CONFIG_SERIAL_RS485CONTROL
   uint8_t rs485mode:1;      /* We are in RS485 (RTS on TX) mode */
+#endif
+  /* TX DMA state */
+
+#ifdef SERIAL_HAVE_TXDMA
+  const unsigned int dma_txreqsrc;  /* DMAMUX source of TX DMA request */
+  DMACH_HANDLE       txdma;         /* currently-open trasnmit DMA stream */
+  sem_t              txdmasem;      /* Indicate TX DMA completion */
+#endif
+
+  /* RX DMA state */
+
+#ifdef SERIAL_HAVE_RXDMA
+  const unsigned int dma_rxreqsrc;  /* DMAMUX source of RX DMA request */
+  DMACH_HANDLE       rxdma;         /* currently-open receive DMA stream */
+  bool               rxenable;      /* DMA-based reception en/disable */
+  uint32_t           rxdmanext;     /* Next byte in the DMA buffer to be read */
+  char *const        rxfifo;        /* Receive DMA buffer */
 #endif
 };
 
@@ -350,12 +541,48 @@ static int  imxrt_attach(struct uart_dev_s *dev);
 static void imxrt_detach(struct uart_dev_s *dev);
 static int  imxrt_interrupt(int irq, void *context, void *arg);
 static int  imxrt_ioctl(struct file *filep, int cmd, unsigned long arg);
+#if !defined(SERIAL_HAVE_ONLY_RXDMA)
 static int  imxrt_receive(struct uart_dev_s *dev, unsigned int *status);
 static void imxrt_rxint(struct uart_dev_s *dev, bool enable);
 static bool imxrt_rxavailable(struct uart_dev_s *dev);
-static void imxrt_send(struct uart_dev_s *dev, int ch);
+#endif
+#if !defined(SERIAL_HAVE_ONLY_TXDMA)
 static void imxrt_txint(struct uart_dev_s *dev, bool enable);
+#endif
+
+#ifdef CONFIG_SERIAL_IFLOWCONTROL
+static bool imxrt_rxflowcontrol(struct uart_dev_s *dev,
+                                unsigned int nbuffered, bool upper);
+#endif
+static void imxrt_send(struct uart_dev_s *dev, int ch);
+
 static bool imxrt_txready(struct uart_dev_s *dev);
+
+#ifdef SERIAL_HAVE_TXDMA
+static void imxrt_dma_send(struct uart_dev_s *dev);
+static void imxrt_dma_txint(struct uart_dev_s *dev, bool enable);
+static void imxrt_dma_txavailable(struct uart_dev_s *dev);
+static void imxrt_dma_txcallback(DMACH_HANDLE handle, void *arg, bool done,
+                                  int result);
+#endif
+
+#if defined(SERIAL_HAVE_RXDMA) || defined(SERIAL_HAVE_TXDMA)
+static int  imxrt_dma_setup(struct uart_dev_s *dev);
+static void imxrt_dma_shutdown(struct uart_dev_s *dev);
+#endif
+
+#ifdef SERIAL_HAVE_RXDMA
+static int  imxrt_dma_receive(struct uart_dev_s *dev, unsigned int *status);
+#ifdef CONFIG_PM
+static void imxrt_dma_reenable(struct imxrt_uart_s *priv);
+#endif
+static void imxrt_dma_rxint(struct uart_dev_s *dev, bool enable);
+static bool imxrt_dma_rxavailable(struct uart_dev_s *dev);
+
+static void imxrt_dma_rxcallback(DMACH_HANDLE handle, void *arg, bool done,
+                                  int result);
+#endif
+
 static bool imxrt_txempty(struct uart_dev_s *dev);
 
 #ifdef CONFIG_PM
@@ -371,7 +598,8 @@ static int  up_pm_prepare(struct pm_callback_s *cb, int domain,
 
 /* Serial driver UART operations */
 
-static const struct uart_ops_s g_uart_ops =
+#if !defined(SERIAL_HAVE_ONLY_TXDMA) && !defined(SERIAL_HAVE_ONLY_RXDMA)
+static const struct uart_ops_s g_lpuart_ops =
 {
   .setup          = imxrt_setup,
   .shutdown       = imxrt_shutdown,
@@ -382,61 +610,210 @@ static const struct uart_ops_s g_uart_ops =
   .rxint          = imxrt_rxint,
   .rxavailable    = imxrt_rxavailable,
 #ifdef CONFIG_SERIAL_IFLOWCONTROL
-  .rxflowcontrol  = NULL,
+  .rxflowcontrol  = imxrt_rxflowcontrol,
+#endif
+  .send           = imxrt_send,
+  .txint          = imxrt_txint,
+  .txready        = imxrt_txready,
+  .txempty        = imxrt_txempty,
+};
+#endif
+
+#if defined(SERIAL_HAVE_RXDMA) && defined(SERIAL_HAVE_TXDMA)
+static const struct uart_ops_s g_lpuart_rxtxdma_ops =
+{
+  .setup          = imxrt_dma_setup,
+  .shutdown       = imxrt_dma_shutdown,
+  .attach         = imxrt_attach,
+  .detach         = imxrt_detach,
+  .ioctl          = imxrt_ioctl,
+  .receive        = imxrt_dma_receive,
+  .rxint          = imxrt_dma_rxint,
+  .rxavailable    = imxrt_dma_rxavailable,
+#ifdef CONFIG_SERIAL_IFLOWCONTROL
+  .rxflowcontrol  = imxrt_rxflowcontrol,
+#endif
+  .send           = imxrt_send,
+  .txint          = imxrt_dma_txint,
+  .txready        = imxrt_txready,
+  .txempty        = imxrt_txempty,
+  .dmatxavail     = imxrt_dma_txavailable,
+  .dmasend        = imxrt_dma_send,
+};
+#endif
+#if !defined(SERIAL_HAVE_ONLY_DMA) && defined(SERIAL_HAVE_RXDMA)
+static const struct uart_ops_s g_lpuart_rxdma_ops =
+{
+  .setup          = imxrt_dma_setup,
+  .shutdown       = imxrt_dma_shutdown,
+  .attach         = imxrt_attach,
+  .detach         = imxrt_detach,
+  .ioctl          = imxrt_ioctl,
+  .receive        = imxrt_dma_receive,
+  .rxint          = imxrt_dma_rxint,
+  .rxavailable    = imxrt_dma_rxavailable,
+#ifdef CONFIG_SERIAL_IFLOWCONTROL
+  .rxflowcontrol  = imxrt_rxflowcontrol,
 #endif
   .send           = imxrt_send,
   .txint          = imxrt_txint,
   .txready        = imxrt_txready,
   .txempty        = imxrt_txempty,
 };
+#endif
+
+#if !defined(SERIAL_HAVE_ONLY_DMA) && defined(SERIAL_HAVE_TXDMA)
+static const struct uart_ops_s g_lpuart_txdma_ops =
+{
+    .setup          = imxrt_dma_setup,
+    .shutdown       = imxrt_dma_shutdown,
+    .attach         = imxrt_attach,
+    .detach         = imxrt_detach,
+    .ioctl          = imxrt_ioctl,
+    .receive        = imxrt_receive,
+    .rxint          = imxrt_rxint,
+    .rxavailable    = imxrt_rxavailable,
+  #ifdef CONFIG_SERIAL_IFLOWCONTROL
+    .rxflowcontrol  = imxrt_rxflowcontrol,
+  #endif
+    .send           = imxrt_send,
+    .txint          = imxrt_dma_txint,
+    .txready        = imxrt_txready,
+    .txempty        = imxrt_txempty,
+    .dmatxavail     = imxrt_dma_txavailable,
+    .dmasend        = imxrt_dma_send,
+};
+#endif
+
+/* Avoid unused warning */
+#if !defined(SERIAL_HAVE_ONLY_DMA) && defined(SERIAL_HAVE_RXDMA)
+const struct uart_ops_s *g_o0 = &g_lpuart_rxdma_ops;
+#endif
+#if !defined(SERIAL_HAVE_ONLY_DMA) && defined(SERIAL_HAVE_TXDMA)
+const struct uart_ops_s *g_o1 = &g_lpuart_txdma_ops;
+#endif
 
 /* I/O buffers */
 
+#ifdef CONFIG_LPUART1_RXDMA
+static char g_lpuart1rxfifo[RXDMA_BUFFER_SIZE]
+  aligned_data(ARMV7M_DCACHE_LINESIZE);
+#endif
+
+# ifdef CONFIG_LPUART2_RXDMA
+static char g_lpuart2rxfifo[RXDMA_BUFFER_SIZE]
+  aligned_data(ARMV7M_DCACHE_LINESIZE);
+#endif
+
+#ifdef CONFIG_LPUART3_RXDMA
+static char g_lpuart3rxfifo[RXDMA_BUFFER_SIZE]
+  aligned_data(ARMV7M_DCACHE_LINESIZE);
+#endif
+
+#ifdef CONFIG_LPUART4_RXDMA
+static char g_lpuart4rxfifo[RXDMA_BUFFER_SIZE]
+  aligned_data(ARMV7M_DCACHE_LINESIZE);
+#endif
+
+#ifdef CONFIG_LPUART5_RXDMA
+static char g_lpuart5rxfifo[RXDMA_BUFFER_SIZE]
+  aligned_data(ARMV7M_DCACHE_LINESIZE);
+#endif
+
+#ifdef CONFIG_LPUART6_RXDMA
+static char g_lpuart6rxfifo[RXDMA_BUFFER_SIZE]
+  aligned_data(ARMV7M_DCACHE_LINESIZE);
+#endif
+
+#ifdef CONFIG_LPUART7_RXDMA
+static char g_lpuart7rxfifo[RXDMA_BUFFER_SIZE]
+  aligned_data(ARMV7M_DCACHE_LINESIZE);
+#endif
+
+#ifdef CONFIG_LPUART8_RXDMA
+static char g_lpuart8rxfifo[RXDMA_BUFFER_SIZE]
+  aligned_data(ARMV7M_DCACHE_LINESIZE);
+#endif
+
+/* Receive/Transmit buffers */
+
 #ifdef CONFIG_IMXRT_LPUART1
-static char g_uart1rxbuffer[CONFIG_LPUART1_RXBUFSIZE];
-static char g_uart1txbuffer[CONFIG_LPUART1_TXBUFSIZE];
+static char g_lpuart1rxbuffer[CONFIG_LPUART1_RXBUFSIZE];
+static char g_lpuart1txbuffer[LPUART1_TXBUFSIZE_ADJUSTED] \
+  LPUART1_TXBUFSIZE_ALGN;
 #endif
 
 #ifdef CONFIG_IMXRT_LPUART2
-static char g_uart2rxbuffer[CONFIG_LPUART2_RXBUFSIZE];
-static char g_uart2txbuffer[CONFIG_LPUART2_TXBUFSIZE];
+static char g_lpuart2rxbuffer[CONFIG_LPUART2_RXBUFSIZE];
+static char g_lpuart2txbuffer[LPUART2_TXBUFSIZE_ADJUSTED] \
+  LPUART2_TXBUFSIZE_ALGN;
 #endif
 
 #ifdef CONFIG_IMXRT_LPUART3
-static char g_uart3rxbuffer[CONFIG_LPUART3_RXBUFSIZE];
-static char g_uart3txbuffer[CONFIG_LPUART3_TXBUFSIZE];
+static char g_lpuart3rxbuffer[CONFIG_LPUART3_RXBUFSIZE];
+static char g_lpuart3txbuffer[LPUART3_TXBUFSIZE_ADJUSTED] \
+  LPUART3_TXBUFSIZE_ALGN;
 #endif
 
 #ifdef CONFIG_IMXRT_LPUART4
-static char g_uart4rxbuffer[CONFIG_LPUART4_RXBUFSIZE];
-static char g_uart4txbuffer[CONFIG_LPUART4_TXBUFSIZE];
+static char g_lpuart4rxbuffer[CONFIG_LPUART4_RXBUFSIZE];
+static char g_lpuart4txbuffer[LPUART4_TXBUFSIZE_ADJUSTED] \
+  LPUART4_TXBUFSIZE_ALGN;
 #endif
 
 #ifdef CONFIG_IMXRT_LPUART5
-static char g_uart5rxbuffer[CONFIG_LPUART5_RXBUFSIZE];
-static char g_uart5txbuffer[CONFIG_LPUART5_TXBUFSIZE];
+static char g_lpuart5rxbuffer[CONFIG_LPUART5_RXBUFSIZE];
+static char g_lpuart5txbuffer[LPUART5_TXBUFSIZE_ADJUSTED] \
+  LPUART5_TXBUFSIZE_ALGN;
 #endif
 
 #ifdef CONFIG_IMXRT_LPUART6
-static char g_uart6rxbuffer[CONFIG_LPUART6_RXBUFSIZE];
-static char g_uart6txbuffer[CONFIG_LPUART6_TXBUFSIZE];
+static char g_lpuart6rxbuffer[CONFIG_LPUART6_RXBUFSIZE];
+static char g_lpuart6txbuffer[LPUART6_TXBUFSIZE_ADJUSTED] \
+  LPUART6_TXBUFSIZE_ALGN;
 #endif
 
 #ifdef CONFIG_IMXRT_LPUART7
-static char g_uart7rxbuffer[CONFIG_LPUART7_RXBUFSIZE];
-static char g_uart7txbuffer[CONFIG_LPUART7_TXBUFSIZE];
+static char g_lpuart7rxbuffer[CONFIG_LPUART7_RXBUFSIZE];
+static char g_lpuart7txbuffer[LPUART7_TXBUFSIZE_ADJUSTED] \
+  LPUART7_TXBUFSIZE_ALGN;
 #endif
 
 #ifdef CONFIG_IMXRT_LPUART8
-static char g_uart8rxbuffer[CONFIG_LPUART8_RXBUFSIZE];
-static char g_uart8txbuffer[CONFIG_LPUART8_TXBUFSIZE];
+static char g_lpuart8rxbuffer[CONFIG_LPUART8_RXBUFSIZE];
+static char g_lpuart8txbuffer[LPUART8_TXBUFSIZE_ADJUSTED] \
+  LPUART8_TXBUFSIZE_ALGN;
 #endif
 
 /* This describes the state of the IMXRT lpuart1 port. */
 
 #ifdef CONFIG_IMXRT_LPUART1
-static struct imxrt_uart_s g_uart1priv =
+static struct imxrt_uart_s g_lpuart1priv =
 {
+  .dev =
+    {
+      .recv         =
+      {
+        .size       = CONFIG_LPUART1_RXBUFSIZE,
+        .buffer     = g_lpuart1rxbuffer,
+      },
+      .xmit         =
+      {
+        .size       = CONFIG_LPUART1_TXBUFSIZE,
+        .buffer     = g_lpuart1txbuffer,
+      },
+    #if defined(CONFIG_LPUART1_RXDMA) && defined(CONFIG_LPUART1_TXDMA)
+        .ops       = &g_lpuart_rxtxdma_ops,
+    #elif defined(CONFIG_LPUART1_RXDMA) && !defined(CONFIG_LPUART1_TXDMA)
+        .ops       = &g_lpuart_rxdma_ops,
+    #elif !defined(CONFIG_LPUART1_RXDMA) && defined(CONFIG_LPUART1_TXDMA)
+        .ops       = &g_lpuart_txdma_ops,
+    #else
+        .ops       = &g_lpuart_ops,
+    #endif
+      .priv         = &g_lpuart1priv,
+    },
+
   .uartbase     = IMXRT_LPUART1_BASE,
   .baud         = CONFIG_LPUART1_BAUD,
   .irq          = IMXRT_IRQ_LPUART1,
@@ -466,30 +843,46 @@ static struct imxrt_uart_s g_uart1priv =
 #if defined(CONFIG_SERIAL_RS485CONTROL) && defined(CONFIG_LPUART1_RS485RTSCONTROL)
   .rs485mode    = 1,
 #endif
-};
 
-static struct uart_dev_s g_uart1port =
-{
-  .recv         =
-  {
-    .size       = CONFIG_LPUART1_RXBUFSIZE,
-    .buffer     = g_uart1rxbuffer,
-  },
-  .xmit         =
-  {
-    .size       = CONFIG_LPUART1_TXBUFSIZE,
-    .buffer     = g_uart1txbuffer,
-  },
-  .ops          = &g_uart_ops,
-  .priv         = &g_uart1priv,
+#ifdef CONFIG_LPUART1_TXDMA
+  .dma_txreqsrc = IMXRT_DMACHAN_LPUART1_TX,
+#endif
+#ifdef CONFIG_LPUART1_RXDMA
+  .dma_rxreqsrc = IMXRT_DMACHAN_LPUART1_RX,
+  .rxfifo        = g_lpuart1rxfifo,
+#endif
 };
 #endif
 
 /* This describes the state of the IMXRT lpuart2 port. */
 
 #ifdef CONFIG_IMXRT_LPUART2
-static struct imxrt_uart_s g_uart2priv =
+static struct imxrt_uart_s g_lpuart2priv =
 {
+    .dev =
+      {
+        .recv         =
+        {
+          .size       = CONFIG_LPUART2_RXBUFSIZE,
+          .buffer     = g_lpuart2rxbuffer,
+        },
+        .xmit         =
+        {
+          .size       = CONFIG_LPUART2_TXBUFSIZE,
+          .buffer     = g_lpuart2txbuffer,
+        },
+      #if defined(CONFIG_LPUART2_RXDMA) && defined(CONFIG_LPUART2_TXDMA)
+          .ops       = &g_lpuart_rxtxdma_ops,
+      #elif defined(CONFIG_LPUART2_RXDMA) && !defined(CONFIG_LPUART2_TXDMA)
+          .ops       = &g_lpuart_rxdma_ops,
+      #elif !defined(CONFIG_LPUART2_RXDMA) && defined(CONFIG_LPUART2_TXDMA)
+          .ops       = &g_lpuart_txdma_ops,
+      #else
+          .ops       = &g_lpuart_ops,
+      #endif
+        .priv         = &g_lpuart2priv,
+      },
+
   .uartbase     = IMXRT_LPUART2_BASE,
   .baud         = CONFIG_LPUART2_BAUD,
   .irq          = IMXRT_IRQ_LPUART2,
@@ -518,28 +911,44 @@ static struct imxrt_uart_s g_uart2priv =
 #if defined(CONFIG_SERIAL_RS485CONTROL) && defined(CONFIG_LPUART2_RS485RTSCONTROL)
   .rs485mode    = 1,
 #endif
-};
 
-static struct uart_dev_s g_uart2port =
-{
-  .recv         =
-  {
-    .size       = CONFIG_LPUART2_RXBUFSIZE,
-    .buffer     = g_uart2rxbuffer,
-  },
-  .xmit         =
-  {
-    .size       = CONFIG_LPUART2_TXBUFSIZE,
-    .buffer     = g_uart2txbuffer,
-  },
-  .ops          = &g_uart_ops,
-  .priv         = &g_uart2priv,
+#ifdef CONFIG_LPUART2_TXDMA
+  .dma_txreqsrc = IMXRT_DMACHAN_LPUART2_TX,
+#endif
+#ifdef CONFIG_LPUART2_RXDMA
+  .dma_rxreqsrc = IMXRT_DMACHAN_LPUART2_RX,
+  .rxfifo        = g_lpuart2rxfifo,
+#endif
 };
 #endif
 
 #ifdef CONFIG_IMXRT_LPUART3
-static struct imxrt_uart_s g_uart3priv =
+static struct imxrt_uart_s g_lpuart3priv =
 {
+  .dev =
+    {
+      .recv         =
+      {
+        .size       = CONFIG_LPUART3_RXBUFSIZE,
+        .buffer     = g_lpuart3rxbuffer,
+      },
+      .xmit         =
+      {
+        .size       = CONFIG_LPUART3_TXBUFSIZE,
+        .buffer     = g_lpuart3txbuffer,
+      },
+    #if defined(CONFIG_LPUART3_RXDMA) && defined(CONFIG_LPUART3_TXDMA)
+        .ops       = &g_lpuart_rxtxdma_ops,
+    #elif defined(CONFIG_LPUART3_RXDMA) && !defined(CONFIG_LPUART3_TXDMA)
+        .ops       = &g_lpuart_rxdma_ops,
+    #elif !defined(CONFIG_LPUART3_RXDMA) && defined(CONFIG_LPUART3_TXDMA)
+        .ops       = &g_lpuart_txdma_ops,
+    #else
+        .ops       = &g_lpuart_ops,
+    #endif
+      .priv         = &g_lpuart3priv,
+    },
+
   .uartbase     = IMXRT_LPUART3_BASE,
   .baud         = CONFIG_LPUART3_BAUD,
   .irq          = IMXRT_IRQ_LPUART3,
@@ -568,28 +977,44 @@ static struct imxrt_uart_s g_uart3priv =
 #if defined(CONFIG_SERIAL_RS485CONTROL) && defined(CONFIG_LPUART3_RS485RTSCONTROL)
   .rs485mode    = 1,
 #endif
-};
 
-static struct uart_dev_s g_uart3port =
-{
-  .recv         =
-  {
-    .size       = CONFIG_LPUART3_RXBUFSIZE,
-    .buffer     = g_uart3rxbuffer,
-  },
-  .xmit         =
-  {
-    .size       = CONFIG_LPUART3_TXBUFSIZE,
-    .buffer     = g_uart3txbuffer,
-  },
-  .ops          = &g_uart_ops,
-  .priv         = &g_uart3priv,
+#ifdef CONFIG_LPUART3_TXDMA
+  .dma_txreqsrc = IMXRT_DMACHAN_LPUART3_TX,
+#endif
+#ifdef CONFIG_LPUART3_RXDMA
+  .dma_rxreqsrc = IMXRT_DMACHAN_LPUART3_RX,
+  .rxfifo        = g_lpuart3rxfifo,
+#endif
 };
 #endif
 
 #ifdef CONFIG_IMXRT_LPUART4
-static struct imxrt_uart_s g_uart4priv =
+static struct imxrt_uart_s g_lpuart4priv =
 {
+  .dev =
+    {
+      .recv         =
+      {
+        .size       = CONFIG_LPUART4_RXBUFSIZE,
+        .buffer     = g_lpuart4rxbuffer,
+      },
+      .xmit         =
+      {
+        .size       = CONFIG_LPUART4_TXBUFSIZE,
+        .buffer     = g_lpuart4txbuffer,
+      },
+    #if defined(CONFIG_LPUART4_RXDMA) && defined(CONFIG_LPUART4_TXDMA)
+        .ops       = &g_lpuart_rxtxdma_ops,
+    #elif defined(CONFIG_LPUART4_RXDMA) && !defined(CONFIG_LPUART4_TXDMA)
+        .ops       = &g_lpuart_rxdma_ops,
+    #elif !defined(CONFIG_LPUART4_RXDMA) && defined(CONFIG_LPUART4_TXDMA)
+        .ops       = &g_lpuart_txdma_ops,
+    #else
+        .ops       = &g_lpuart_ops,
+    #endif
+      .priv         = &g_lpuart4priv,
+    },
+
   .uartbase     = IMXRT_LPUART4_BASE,
   .baud         = CONFIG_LPUART4_BAUD,
   .irq          = IMXRT_IRQ_LPUART4,
@@ -618,28 +1043,44 @@ static struct imxrt_uart_s g_uart4priv =
 #if defined(CONFIG_SERIAL_RS485CONTROL) && defined(CONFIG_LPUART4_RS485RTSCONTROL)
   .rs485mode    = 1,
 #endif
-};
 
-static struct uart_dev_s g_uart4port =
-{
-  .recv         =
-  {
-    .size       = CONFIG_LPUART4_RXBUFSIZE,
-    .buffer     = g_uart4rxbuffer,
-  },
-  .xmit         =
-  {
-    .size       = CONFIG_LPUART4_TXBUFSIZE,
-    .buffer     = g_uart4txbuffer,
-  },
-  .ops          = &g_uart_ops,
-  .priv         = &g_uart4priv,
+#ifdef CONFIG_LPUART4_TXDMA
+  .dma_txreqsrc = IMXRT_DMACHAN_LPUART4_TX,
+#endif
+#ifdef CONFIG_LPUART4_RXDMA
+  .dma_rxreqsrc = IMXRT_DMACHAN_LPUART4_RX,
+  .rxfifo        = g_lpuart4rxfifo,
+#endif
 };
 #endif
 
 #ifdef CONFIG_IMXRT_LPUART5
-static struct imxrt_uart_s g_uart5priv =
+static struct imxrt_uart_s g_lpuart5priv =
 {
+  .dev =
+    {
+      .recv         =
+        {
+          .size       = CONFIG_LPUART5_RXBUFSIZE,
+          .buffer     = g_lpuart5rxbuffer,
+        },
+        .xmit         =
+        {
+          .size       = CONFIG_LPUART5_TXBUFSIZE,
+          .buffer     = g_lpuart5txbuffer,
+        },
+      #if defined(CONFIG_LPUART5_RXDMA) && defined(CONFIG_LPUART5_TXDMA)
+          .ops       = &g_lpuart_rxtxdma_ops,
+      #elif defined(CONFIG_LPUART5_RXDMA) && !defined(CONFIG_LPUART5_TXDMA)
+          .ops       = &g_lpuart_rxdma_ops,
+      #elif !defined(CONFIG_LPUART5_RXDMA) && defined(CONFIG_LPUART5_TXDMA)
+          .ops       = &g_lpuart_txdma_ops,
+      #else
+          .ops       = &g_lpuart_ops,
+      #endif
+        .priv         = &g_lpuart5priv,
+    },
+
   .uartbase     = IMXRT_LPUART5_BASE,
   .baud         = CONFIG_LPUART5_BAUD,
   .irq          = IMXRT_IRQ_LPUART5,
@@ -668,28 +1109,44 @@ static struct imxrt_uart_s g_uart5priv =
 #if defined(CONFIG_SERIAL_RS485CONTROL) && defined(CONFIG_LPUART5_RS485RTSCONTROL)
   .rs485mode    = 1,
 #endif
-};
 
-static struct uart_dev_s g_uart5port =
-{
-  .recv         =
-  {
-    .size       = CONFIG_LPUART5_RXBUFSIZE,
-    .buffer     = g_uart5rxbuffer,
-  },
-  .xmit         =
-  {
-    .size       = CONFIG_LPUART5_TXBUFSIZE,
-    .buffer     = g_uart5txbuffer,
-  },
-  .ops          = &g_uart_ops,
-  .priv         = &g_uart5priv,
+#ifdef CONFIG_LPUART5_TXDMA
+  .dma_txreqsrc = IMXRT_DMACHAN_LPUART5_TX,
+#endif
+#ifdef CONFIG_LPUART5_RXDMA
+  .dma_rxreqsrc = IMXRT_DMACHAN_LPUART5_RX,
+  .rxfifo        = g_lpuart5rxfifo,
+#endif
 };
 #endif
 
 #ifdef CONFIG_IMXRT_LPUART6
-static struct imxrt_uart_s g_uart6priv =
+static struct imxrt_uart_s g_lpuart6priv =
 {
+  .dev =
+    {
+      .recv         =
+      {
+        .size       = CONFIG_LPUART6_RXBUFSIZE,
+        .buffer     = g_lpuart6rxbuffer,
+      },
+      .xmit         =
+      {
+        .size       = CONFIG_LPUART6_TXBUFSIZE,
+        .buffer     = g_lpuart6txbuffer,
+      },
+    #if defined(CONFIG_LPUART6_RXDMA) && defined(CONFIG_LPUART6_TXDMA)
+        .ops       = &g_lpuart_rxtxdma_ops,
+    #elif defined(CONFIG_LPUART6_RXDMA) && !defined(CONFIG_LPUART6_TXDMA)
+        .ops       = &g_lpuart_rxdma_ops,
+    #elif !defined(CONFIG_LPUART6_RXDMA) && defined(CONFIG_LPUART6_TXDMA)
+        .ops       = &g_lpuart_txdma_ops,
+    #else
+        .ops       = &g_lpuart_ops,
+    #endif
+      .priv         = &g_lpuart6priv,
+    },
+
   .uartbase     = IMXRT_LPUART6_BASE,
   .baud         = CONFIG_LPUART6_BAUD,
   .irq          = IMXRT_IRQ_LPUART6,
@@ -718,28 +1175,44 @@ static struct imxrt_uart_s g_uart6priv =
 #if defined(CONFIG_SERIAL_RS485CONTROL) && defined(CONFIG_LPUART6_RS485RTSCONTROL)
   .rs485mode    = 1,
 #endif
-};
 
-static struct uart_dev_s g_uart6port =
-{
-  .recv         =
-  {
-    .size       = CONFIG_LPUART6_RXBUFSIZE,
-    .buffer     = g_uart6rxbuffer,
-  },
-  .xmit         =
-  {
-    .size       = CONFIG_LPUART6_TXBUFSIZE,
-    .buffer     = g_uart6txbuffer,
-  },
-  .ops          = &g_uart_ops,
-  .priv         = &g_uart6priv,
+#ifdef CONFIG_LPUART6_TXDMA
+  .dma_txreqsrc = IMXRT_DMACHAN_LPUART6_TX,
+#endif
+#ifdef CONFIG_LPUART6_RXDMA
+  .dma_rxreqsrc = IMXRT_DMACHAN_LPUART6_RX,
+  .rxfifo        = g_lpuart6rxfifo,
+#endif
 };
 #endif
 
 #ifdef CONFIG_IMXRT_LPUART7
-static struct imxrt_uart_s g_uart7priv =
+static struct imxrt_uart_s g_lpuart7priv =
 {
+  .dev =
+    {
+      .recv         =
+      {
+        .size       = CONFIG_LPUART7_RXBUFSIZE,
+        .buffer     = g_lpuart7rxbuffer,
+      },
+      .xmit         =
+      {
+        .size       = CONFIG_LPUART7_TXBUFSIZE,
+        .buffer     = g_lpuart7txbuffer,
+      },
+    #if defined(CONFIG_LPUART7_RXDMA) && defined(CONFIG_LPUART7_TXDMA)
+        .ops       = &g_lpuart_rxtxdma_ops,
+    #elif defined(CONFIG_LPUART7_RXDMA) && !defined(CONFIG_LPUART7_TXDMA)
+        .ops       = &g_lpuart_rxdma_ops,
+    #elif !defined(CONFIG_LPUART7_RXDMA) && defined(CONFIG_LPUART7_TXDMA)
+        .ops       = &g_lpuart_txdma_ops,
+    #else
+        .ops       = &g_lpuart_ops,
+    #endif
+      .priv         = &g_lpuart7priv,
+    },
+
   .uartbase     = IMXRT_LPUART7_BASE,
   .baud         = CONFIG_LPUART7_BAUD,
   .irq          = IMXRT_IRQ_LPUART7,
@@ -768,28 +1241,44 @@ static struct imxrt_uart_s g_uart7priv =
 #if defined(CONFIG_SERIAL_RS485CONTROL) && defined(CONFIG_LPUART7_RS485RTSCONTROL)
   .rs485mode    = 1,
 #endif
-};
 
-static struct uart_dev_s g_uart7port =
-{
-  .recv         =
-  {
-    .size       = CONFIG_LPUART7_RXBUFSIZE,
-    .buffer     = g_uart7rxbuffer,
-  },
-  .xmit         =
-  {
-    .size       = CONFIG_LPUART7_TXBUFSIZE,
-    .buffer     = g_uart7txbuffer,
-  },
-  .ops          = &g_uart_ops,
-  .priv         = &g_uart7priv,
+#ifdef CONFIG_LPUART7_TXDMA
+  .dma_txreqsrc = IMXRT_DMACHAN_LPUART7_TX,
+#endif
+#ifdef CONFIG_LPUART7_RXDMA
+  .dma_rxreqsrc = IMXRT_DMACHAN_LPUART7_RX,
+  .rxfifo        = g_lpuart7rxfifo,
+#endif
 };
 #endif
 
 #ifdef CONFIG_IMXRT_LPUART8
-static struct imxrt_uart_s g_uart8priv =
+static struct imxrt_uart_s g_lpuart8priv =
 {
+  .dev =
+    {
+      .recv         =
+      {
+        .size       = CONFIG_LPUART8_RXBUFSIZE,
+        .buffer     = g_lpuart8rxbuffer,
+      },
+      .xmit         =
+      {
+        .size       = CONFIG_LPUART8_TXBUFSIZE,
+        .buffer     = g_lpuart8txbuffer,
+      },
+    #if defined(CONFIG_LPUART8_RXDMA) && defined(CONFIG_LPUART8_TXDMA)
+        .ops       = &g_lpuart_rxtxdma_ops,
+    #elif defined(CONFIG_LPUART8_RXDMA) && !defined(CONFIG_LPUART8_TXDMA)
+        .ops       = &g_lpuart_rxdma_ops,
+    #elif !defined(CONFIG_LPUART8_RXDMA) && defined(CONFIG_LPUART8_TXDMA)
+        .ops       = &g_lpuart_txdma_ops,
+    #else
+        .ops       = &g_lpuart_ops,
+    #endif
+      .priv         = &g_lpuart8priv,
+    },
+
   .uartbase     = IMXRT_LPUART8_BASE,
   .baud         = CONFIG_LPUART8_BAUD,
   .irq          = IMXRT_IRQ_LPUART8,
@@ -818,22 +1307,14 @@ static struct imxrt_uart_s g_uart8priv =
 #if defined(CONFIG_SERIAL_RS485CONTROL) && defined(CONFIG_LPUART8_RS485RTSCONTROL)
   .rs485mode    = 1,
 #endif
-};
 
-static struct uart_dev_s g_uart8port =
-{
-  .recv         =
-  {
-    .size       = CONFIG_LPUART8_RXBUFSIZE,
-    .buffer     = g_uart8rxbuffer,
-  },
-  .xmit         =
-  {
-    .size       = CONFIG_LPUART8_TXBUFSIZE,
-    .buffer     = g_uart8txbuffer,
-  },
-  .ops          = &g_uart_ops,
-  .priv         = &g_uart8priv,
+#ifdef CONFIG_LPUART8_TXDMA
+  .dma_txreqsrc = IMXRT_DMACHAN_LPUART8_TX,
+#endif
+#ifdef CONFIG_LPUART8_RXDMA
+  .dma_rxreqsrc = IMXRT_DMACHAN_LPUART8_RX,
+  .rxfifo        = g_lpuart8rxfifo,
+#endif
 };
 #endif
 
@@ -869,6 +1350,24 @@ static inline void imxrt_serialout(struct imxrt_uart_s *priv,
   putreg32(value, priv->uartbase + offset);
 }
 
+/****************************************************************************
+ * Name: imxrt_dma_nextrx
+ *
+ * Description:
+ *   Returns the index into the RX FIFO where the DMA will place the next
+ *   byte that it receives.
+ *
+ ****************************************************************************/
+
+#ifdef SERIAL_HAVE_RXDMA
+static int imxrt_dma_nextrx(struct imxrt_uart_s *priv)
+{
+  int dmaresidual = imxrt_dmach_getcount(priv->rxdma);
+
+  return RXDMA_BUFFER_SIZE - dmaresidual;
+}
+#endif
+
 /****************************************************************************
  * Name: imxrt_disableuartint
  ****************************************************************************/
@@ -916,6 +1415,132 @@ static inline void imxrt_restoreuartint(struct imxrt_uart_s *priv,
   spin_unlock_irqrestore(NULL, flags);
 }
 
+/****************************************************************************
+ * Name: imxrt_dma_setup
+ *
+ * Description:
+ *   Configure the LPUART baud, bits, parity, etc. This method is called the
+ *   first time that the serial port is opened.
+ *
+ ****************************************************************************/
+
+#if defined(SERIAL_HAVE_RXDMA) || defined(SERIAL_HAVE_TXDMA)
+static int imxrt_dma_setup(struct uart_dev_s *dev)
+{
+  struct imxrt_uart_s *priv = (struct imxrt_uart_s *)dev;
+#if defined(SERIAL_HAVE_RXDMA)
+  struct imxrt_edma_xfrconfig_s config;
+#endif
+  int result;
+
+  /* Do the basic UART setup first, unless we are the console */
+
+  if (!dev->isconsole)
+    {
+      result = imxrt_setup(dev);
+      if (result != OK)
+        {
+          return result;
+        }
+    }
+
+#if defined(SERIAL_HAVE_TXDMA)
+  /* Acquire the Tx DMA channel.  This should always succeed. */
+
+  if (priv->dma_txreqsrc != 0)
+    {
+      if (priv->txdma == NULL)
+        {
+          priv->txdma = imxrt_dmach_alloc(priv->dma_txreqsrc |
+                                          DMAMUX_CHCFG_ENBL, 0);
+          if (priv->txdma == NULL)
+            {
+              return -EBUSY;
+            }
+
+          nxsem_init(&priv->txdmasem, 0, 1);
+          nxsem_set_protocol(&priv->txdmasem, SEM_PRIO_NONE);
+        }
+
+      /* Enable Tx DMA for the UART */
+
+      modifyreg32(priv->uartbase + IMXRT_LPUART_BAUD_OFFSET,
+                  0, LPUART_BAUD_TDMAE);
+    }
+#endif
+
+#if defined(SERIAL_HAVE_RXDMA)
+  /* Acquire the Rx DMA channel.  This should always succeed. */
+
+  if (priv->dma_rxreqsrc != 0)
+    {
+      if (priv->rxdma == NULL)
+        {
+          priv->rxdma = imxrt_dmach_alloc(priv->dma_rxreqsrc |
+                                          DMAMUX_CHCFG_ENBL, 0);
+
+          if (priv->rxdma == NULL)
+            {
+              return -EBUSY;
+            }
+        }
+      else
+        {
+          imxrt_dmach_stop(priv->rxdma);
+        }
+
+      /* Configure for circular DMA reception into the RX FIFO */
+
+      config.saddr  = priv->uartbase + IMXRT_LPUART_DATA_OFFSET;
+      config.daddr  = (uint32_t) priv->rxfifo;
+      config.soff   = 0;
+      config.doff   = 1;
+      config.iter   = RXDMA_BUFFER_SIZE;
+      config.flags  = EDMA_CONFIG_LINKTYPE_LINKNONE |
+                      EDMA_CONFIG_LOOPDEST |
+                      EDMA_CONFIG_INTHALF  |
+                      EDMA_CONFIG_INTMAJOR;
+      config.ssize  = EDMA_8BIT;
+      config.dsize  = EDMA_8BIT;
+      config.nbytes = 1;
+    #ifdef CONFIG_KINETIS_EDMA_ELINK
+      config.linkch = 0;
+    #endif
+
+      imxrt_dmach_xfrsetup(priv->rxdma , &config);
+
+      /* Reset our DMA shadow pointer and Rx data availability count to
+       * match the address just programmed above.
+       */
+
+      priv->rxdmanext = 0;
+
+      /* Enable receive Rx DMA for the UART */
+
+      modifyreg32(priv->uartbase + IMXRT_LPUART_BAUD_OFFSET,
+                  0, LPUART_BAUD_RDMAE);
+
+      /* Enable itnerrupt on Idel and erros */
+
+      modifyreg32(priv->uartbase + IMXRT_LPUART_CTRL_OFFSET, 0,
+                  LPUART_CTRL_PEIE       |
+                  LPUART_CTRL_FEIE       |
+                  LPUART_CTRL_NEIE       |
+                  LPUART_CTRL_ILIE);
+
+      /* Start the DMA channel, and arrange for callbacks at the half and
+       * full points in the FIFO.  This ensures that we have half a FIFO
+       * worth of time to claim bytes before they are overwritten.
+       */
+
+      imxrt_dmach_start(priv->rxdma, imxrt_dma_rxcallback, (void *)priv);
+    }
+#endif
+
+  return OK;
+}
+#endif
+
 /****************************************************************************
  * Name: imxrt_setup
  *
@@ -928,7 +1553,7 @@ static inline void imxrt_restoreuartint(struct imxrt_uart_s *priv,
 
 static int imxrt_setup(struct uart_dev_s *dev)
 {
-  struct imxrt_uart_s *priv = (struct imxrt_uart_s *)dev->priv;
+  struct imxrt_uart_s *priv = (struct imxrt_uart_s *)dev;
 #ifndef CONFIG_SUPPRESS_LPUART_CONFIG
   int ret;
   struct uart_config_s config =
@@ -946,7 +1571,13 @@ static int imxrt_setup(struct uart_dev_s *dev)
   config.usects     = priv->iflow;      /* Flow control on inbound side */
 #endif
 #ifdef CONFIG_SERIAL_OFLOWCONTROL
-  config.userts     = priv->oflow;      /* Flow control on outbound side */
+  /* Flow control on outbound side if not GPIO based */
+
+  if ((priv->rts_gpio & GPIO_MODE_MASK) == GPIO_PERIPH)
+    {
+      config.userts = priv->oflow;
+    }
+
 #endif
 #ifdef CONFIG_SERIAL_RS485CONTROL
   config.users485   = priv->rs485mode;  /* Switch into RS485 mode */
@@ -979,13 +1610,62 @@ static int imxrt_setup(struct uart_dev_s *dev)
 
 static void imxrt_shutdown(struct uart_dev_s *dev)
 {
-  struct imxrt_uart_s *priv = (struct imxrt_uart_s *)dev->priv;
+  struct imxrt_uart_s *priv = (struct imxrt_uart_s *)dev;
 
   /* Disable the UART */
 
   imxrt_serialout(priv, IMXRT_LPUART_GLOBAL_OFFSET, LPUART_GLOBAL_RST);
 }
 
+/****************************************************************************
+ * Name: imxrt_dma_shutdown
+ *
+ * Description:
+ *   Disable the LPUART.  This method is called when the serial
+ *   port is closed
+ *
+ ****************************************************************************/
+
+#if defined(SERIAL_HAVE_RXDMA) || defined(SERIAL_HAVE_TXDMA)
+static void imxrt_dma_shutdown(struct uart_dev_s *dev)
+{
+  struct imxrt_uart_s *priv = (struct imxrt_uart_s *)dev;
+
+  /* Perform the normal UART shutdown */
+
+  imxrt_shutdown(dev);
+
+#if defined(SERIAL_HAVE_RXDMA)
+  /* Stop the RX DMA channel */
+
+  if (priv->dma_rxreqsrc != 0)
+    {
+      imxrt_dmach_stop(priv->rxdma);
+
+      /* Release the RX DMA channel */
+
+      imxrt_dmach_free(priv->rxdma);
+      priv->rxdma = NULL;
+    }
+#endif
+
+#if defined(SERIAL_HAVE_TXDMA)
+  /* Stop the TX DMA channel */
+
+  if (priv->dma_txreqsrc != 0)
+    {
+      imxrt_dmach_stop(priv->txdma);
+
+      /* Release the TX DMA channel */
+
+      imxrt_dmach_free(priv->txdma);
+      priv->txdma = NULL;
+      nxsem_destroy(&priv->txdmasem);
+    }
+#endif
+}
+#endif
+
 /****************************************************************************
  * Name: imxrt_attach
  *
@@ -1004,7 +1684,7 @@ static void imxrt_shutdown(struct uart_dev_s *dev)
 
 static int imxrt_attach(struct uart_dev_s *dev)
 {
-  struct imxrt_uart_s *priv = (struct imxrt_uart_s *)dev->priv;
+  struct imxrt_uart_s *priv = (struct imxrt_uart_s *)dev;
   int ret;
 
   /* Attach and enable the IRQ */
@@ -1034,7 +1714,7 @@ static int imxrt_attach(struct uart_dev_s *dev)
 
 static void imxrt_detach(struct uart_dev_s *dev)
 {
-  struct imxrt_uart_s *priv = (struct imxrt_uart_s *)dev->priv;
+  struct imxrt_uart_s *priv = (struct imxrt_uart_s *)dev;
 
   up_disable_irq(priv->irq);
   irq_detach(priv->irq);
@@ -1052,14 +1732,12 @@ static void imxrt_detach(struct uart_dev_s *dev)
 
 static int imxrt_interrupt(int irq, void *context, void *arg)
 {
-  struct uart_dev_s *dev = (struct uart_dev_s *)arg;
-  struct imxrt_uart_s *priv;
+  struct imxrt_uart_s *priv = (struct imxrt_uart_s *)arg;
   uint32_t usr;
   int passes = 0;
   bool handled;
 
-  DEBUGASSERT(dev != NULL && dev->priv != NULL);
-  priv = (struct imxrt_uart_s *)dev->priv;
+  DEBUGASSERT(priv != NULL);
 
 #if defined(CONFIG_PM) && CONFIG_IMXRT_PM_SERIAL_ACTIVITY > 0
   /* Report serial activity to the power management logic */
@@ -1082,26 +1760,54 @@ static int imxrt_interrupt(int irq, void *context, void *arg)
 
       usr  = imxrt_serialin(priv, IMXRT_LPUART_STAT_OFFSET);
       usr &= (LPUART_STAT_RDRF | LPUART_STAT_TDRE | LPUART_STAT_OR |
-              LPUART_STAT_FE);
+              LPUART_STAT_FE | LPUART_STAT_NF | LPUART_STAT_PF |
+              LPUART_STAT_IDLE);
 
-      /* Clear serial overrun and framing errors */
+      /* Clear serial overrun, parity and framing errors */
 
       if ((usr & LPUART_STAT_OR) != 0)
         {
           imxrt_serialout(priv, IMXRT_LPUART_STAT_OFFSET, LPUART_STAT_OR);
         }
 
+      if ((usr & LPUART_STAT_PF) != 0)
+        {
+          imxrt_serialout(priv, IMXRT_LPUART_STAT_OFFSET, LPUART_STAT_NF);
+        }
+
+      if ((usr & LPUART_STAT_PF) != 0)
+        {
+          imxrt_serialout(priv, IMXRT_LPUART_STAT_OFFSET, LPUART_STAT_PF);
+        }
+
       if ((usr & LPUART_STAT_FE) != 0)
         {
           imxrt_serialout(priv, IMXRT_LPUART_STAT_OFFSET, LPUART_STAT_FE);
         }
 
+      if ((usr & (LPUART_STAT_FE | LPUART_STAT_PF | LPUART_STAT_NF)) != 0)
+        {
+          /* Discard data */
+
+          imxrt_serialin(priv, IMXRT_LPUART_DATA_OFFSET);
+        }
+
+#ifdef SERIAL_HAVE_RXDMA
+      /* The line going to idle, deliver any fractions of RX data */
+
+      if ((usr & LPUART_STAT_IDLE) != 0)
+        {
+          imxrt_serialout(priv, IMXRT_LPUART_STAT_OFFSET, LPUART_STAT_IDLE);
+          imxrt_dma_rxcallback(priv->rxdma, priv, false, LPUART_STAT_IDLE);
+        }
+#endif
+
       /* Handle incoming, receive bytes */
 
       if ((usr & LPUART_STAT_RDRF) != 0 &&
           (priv->ie & LPUART_CTRL_RIE) != 0)
         {
-          uart_recvchars(dev);
+          uart_recvchars(&priv->dev);
           handled = true;
         }
 
@@ -1110,7 +1816,7 @@ static int imxrt_interrupt(int irq, void *context, void *arg)
       if ((usr & LPUART_STAT_TDRE) != 0 &&
           (priv->ie & LPUART_CTRL_TIE) != 0)
         {
-          uart_xmitchars(dev);
+          uart_xmitchars(&priv->dev);
           handled = true;
         }
     }
@@ -1157,7 +1863,7 @@ static int imxrt_ioctl(struct file *filep, int cmd, unsigned long arg)
     case TCGETS:
       {
         struct termios  *termiosp = (struct termios *)arg;
-        struct imxrt_uart_s *priv = (struct imxrt_uart_s *)dev->priv;
+        struct imxrt_uart_s *priv = (struct imxrt_uart_s *)dev;
 
         if (!termiosp)
           {
@@ -1219,7 +1925,7 @@ static int imxrt_ioctl(struct file *filep, int cmd, unsigned long arg)
     case TCSETS:
       {
         struct termios  *termiosp = (struct termios *)arg;
-        struct imxrt_uart_s *priv = (struct imxrt_uart_s *)dev->priv;
+        struct imxrt_uart_s *priv = (struct imxrt_uart_s *)dev;
         uint32_t baud;
         uint32_t ie;
         uint8_t parity;
@@ -1311,7 +2017,7 @@ static int imxrt_ioctl(struct file *filep, int cmd, unsigned long arg)
 
             flags  = spin_lock_irqsave(NULL);
             imxrt_disableuartint(priv, &ie);
-            ret = imxrt_setup(dev);
+            ret = dev->ops->setup(dev);
 
             /* Restore the interrupt state */
 
@@ -1328,7 +2034,7 @@ static int imxrt_ioctl(struct file *filep, int cmd, unsigned long arg)
       {
         uint32_t regval;
         irqstate_t flags;
-        struct imxrt_uart_s *priv = (struct imxrt_uart_s *)dev->priv;
+        struct imxrt_uart_s *priv = (struct imxrt_uart_s *)dev;
 
         flags  = spin_lock_irqsave(NULL);
         regval   = imxrt_serialin(priv, IMXRT_LPUART_CTRL_OFFSET);
@@ -1368,7 +2074,7 @@ static int imxrt_ioctl(struct file *filep, int cmd, unsigned long arg)
         uint32_t stat;
         uint32_t regval;
         irqstate_t flags;
-        struct imxrt_uart_s *priv = (struct imxrt_uart_s *)dev->priv;
+        struct imxrt_uart_s *priv = (struct imxrt_uart_s *)dev;
 
         flags  = spin_lock_irqsave(NULL);
         ctrl   = imxrt_serialin(priv, IMXRT_LPUART_CTRL_OFFSET);
@@ -1431,15 +2137,17 @@ static int imxrt_ioctl(struct file *filep, int cmd, unsigned long arg)
  *
  ****************************************************************************/
 
+#ifndef SERIAL_HAVE_ONLY_RXDMA
 static int imxrt_receive(struct uart_dev_s *dev, unsigned int *status)
 {
-  struct imxrt_uart_s *priv = (struct imxrt_uart_s *)dev->priv;
+  struct imxrt_uart_s *priv = (struct imxrt_uart_s *)dev;
   uint32_t rxd;
 
   rxd     = imxrt_serialin(priv, IMXRT_LPUART_DATA_OFFSET);
   *status = rxd >> LPUART_DATA_STATUS_SHIFT;
   return (rxd & LPUART_DATA_MASK) >> LPUART_DATA_SHIFT;
 }
+#endif
 
 /****************************************************************************
  * Name: imxrt_rxint
@@ -1449,9 +2157,10 @@ static int imxrt_receive(struct uart_dev_s *dev, unsigned int *status)
  *
  ****************************************************************************/
 
+#ifndef SERIAL_HAVE_ONLY_RXDMA
 static void imxrt_rxint(struct uart_dev_s *dev, bool enable)
 {
-  struct imxrt_uart_s *priv = (struct imxrt_uart_s *)dev->priv;
+  struct imxrt_uart_s *priv = (struct imxrt_uart_s *)dev;
   irqstate_t flags;
   uint32_t regval;
 
@@ -1475,6 +2184,7 @@ static void imxrt_rxint(struct uart_dev_s *dev, bool enable)
   imxrt_serialout(priv, IMXRT_LPUART_CTRL_OFFSET, regval);
   spin_unlock_irqrestore(NULL, flags);
 }
+#endif
 
 /****************************************************************************
  * Name: imxrt_rxavailable
@@ -1484,9 +2194,10 @@ static void imxrt_rxint(struct uart_dev_s *dev, bool enable)
  *
  ****************************************************************************/
 
+#ifndef SERIAL_HAVE_ONLY_RXDMA
 static bool imxrt_rxavailable(struct uart_dev_s *dev)
 {
-  struct imxrt_uart_s *priv = (struct imxrt_uart_s *)dev->priv;
+  struct imxrt_uart_s *priv = (struct imxrt_uart_s *)dev;
   uint32_t regval;
 
   /* Return true is data is ready in the Rx FIFO */
@@ -1494,6 +2205,369 @@ static bool imxrt_rxavailable(struct uart_dev_s *dev)
   regval = imxrt_serialin(priv, IMXRT_LPUART_STAT_OFFSET);
   return ((regval & LPUART_STAT_RDRF) != 0);
 }
+#endif
+
+/****************************************************************************
+ * Name: imxrt_rxflowcontrol
+ *
+ * Description:
+ *   Called when Rx buffer is full (or exceeds configured watermark levels
+ *   if CONFIG_SERIAL_IFLOWCONTROL_WATERMARKS is defined).
+ *   Return true if UART activated RX flow control to block more incoming
+ *   data
+ *
+ * Input Parameters:
+ *   dev       - UART device instance
+ *   nbuffered - the number of characters currently buffered
+ *               (if CONFIG_SERIAL_IFLOWCONTROL_WATERMARKS is
+ *               not defined the value will be 0 for an empty buffer or the
+ *               defined buffer size for a full buffer)
+ *   upper     - true indicates the upper watermark was crossed where
+ *               false indicates the lower watermark has been crossed
+ *
+ * Returned Value:
+ *   true if RX flow control activated.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SERIAL_IFLOWCONTROL
+static bool imxrt_rxflowcontrol(struct uart_dev_s *dev,
+                             unsigned int nbuffered, bool upper)
+{
+  struct imxrt_uart_s *priv = (struct imxrt_uart_s *)dev;
+  bool use_swhs = false;
+
+#if defined(CONFIG_SERIAL_IFLOWCONTROL_WATERMARKS)
+  use_swhs = (priv->rts_gpio & GPIO_MODE_MASK) == GPIO_OUTPUT;
+#endif
+
+  if (use_swhs && priv->iflow && (priv->rts_gpio != 0))
+    {
+      /* Assert/de-assert nRTS set it high resume/stop sending */
+
+      imxrt_gpio_write(priv->rts_gpio, upper);
+
+      if (upper)
+        {
+          /* With heavy Rx traffic, RXNE might be set and data pending.
+           * Returning 'true' in such case would cause RXNE left unhandled
+           * and causing interrupt storm. Sending end might be also be slow
+           * to react on nRTS, and returning 'true' here would prevent
+           * processing that data.
+           *
+           * Therefore, return 'false' so input data is still being processed
+           * until sending end reacts on nRTS signal and stops sending more.
+           */
+
+          return false;
+        }
+
+      return upper;
+    }
+  else
+    {
+      /* Is the RX buffer full? */
+
+      if (upper)
+        {
+          /* Disable Rx interrupt to prevent more data being from
+           * peripheral.  When hardware RTS is enabled, this will
+           * prevent more data from coming in.
+           *
+           * This function is only called when UART recv buffer is full,
+           * that is: "dev->recv.head + 1 == dev->recv.tail".
+           *
+           * Logic in "uart_read" will automatically toggle Rx interrupts
+           * when buffer is read empty and thus we do not have to re-
+           * enable Rx interrupts.
+           */
+
+          uart_disablerxint(dev);
+          return true;
+        }
+
+      /* No.. The RX buffer is empty */
+
+      else
+        {
+          /* We might leave Rx interrupt disabled if full recv buffer was
+           * read empty.  Enable Rx interrupt to make sure that more input is
+           * received.
+           */
+
+          uart_enablerxint(dev);
+        }
+    }
+
+  return false;
+}
+#endif
+
+/****************************************************************************
+ * Name: imxrt_dma_receive
+ *
+ * Description:
+ *   Called (usually) from the interrupt level to receive one
+ *   character from the LPUART.  Error bits associated with the
+ *   receipt are provided in the return 'status'.
+ *
+ ****************************************************************************/
+
+#ifdef SERIAL_HAVE_RXDMA
+static int imxrt_dma_receive(struct uart_dev_s *dev, unsigned int *status)
+{
+  struct imxrt_uart_s *priv = (struct imxrt_uart_s *)dev;
+  uint32_t nextrx = imxrt_dma_nextrx(priv);
+  int c = 0;
+
+  /* Check if more data is available */
+
+  if (nextrx != priv->rxdmanext)
+    {
+      /* Now read from the DMA buffer */
+
+      c = priv->rxfifo[priv->rxdmanext];
+
+      priv->rxdmanext++;
+
+      if (priv->rxdmanext == RXDMA_BUFFER_SIZE)
+        {
+          priv->rxdmanext = 0;
+        }
+    }
+
+  /* NOTE:  If no data is available, then we would return NULL which is,
+   * of course, valid binary data.  The protocol is that the upper half
+   * driver must call imxrt_dma_rxavailable prior to calling this function to
+   * assure that this never happens.
+   */
+
+  return c;
+}
+#endif
+
+/****************************************************************************
+ * Name: imxrt_dma_reenable
+ *
+ * Description:
+ *   Call to re-enable RX DMA.
+ *
+ ****************************************************************************/
+
+#if defined(SERIAL_HAVE_RXDMA) && defined(CONFIG_PM)
+static void imxrt_dma_reenable(struct imxrt_uart_s *priv)
+{
+  struct imxrt_edma_xfrconfig_s config;
+
+  /* Stop an reset the RX DMA */
+
+  imxrt_dmach_stop(priv->rxdma);
+
+  /* Configure for circular DMA reception into the RX FIFO */
+
+  config.saddr  = priv->uartbase + IMXRT_LPUART_DATA_OFFSET;
+  config.daddr  = (uint32_t) priv->rxfifo;
+  config.soff   = 0;
+  config.doff   = 1;
+  config.iter   = RXDMA_BUFFER_SIZE;
+  config.flags  = EDMA_CONFIG_LINKTYPE_LINKNONE |
+                  EDMA_CONFIG_LOOPDEST |
+                  EDMA_CONFIG_INTHALF |
+                  EDMA_CONFIG_INTMAJOR;
+  config.ssize  = EDMA_8BIT;
+  config.dsize  = EDMA_8BIT;
+  config.nbytes = 1;
+#ifdef CONFIG_KINETIS_EDMA_ELINK
+  config.linkch = 0;
+#endif
+
+  imxrt_dmach_xfrsetup(priv->rxdma, &config);
+
+  /* Reset our DMA shadow pointer and Rx data availability count to match
+   * the address just programmed above.
+   */
+
+  priv->rxdmanext = 0;
+
+  /* Start the DMA channel, and arrange for callbacks at the half and
+   * full points in the FIFO.  This ensures that we have half a FIFO
+   * worth of time to claim bytes before they are overwritten.
+   */
+
+  imxrt_dmach_start(priv->rxdma, imxrt_dma_rxcallback, (void *)priv);
+
+  /* Clear DMA suspended flag. */
+
+  priv->rxdmasusp  = false;
+}
+#endif
+
+/****************************************************************************
+ * Name: imxrt_dma_rxint
+ *
+ * Description:
+ *   Call to enable or disable RX interrupts
+ *
+ ****************************************************************************/
+
+#ifdef SERIAL_HAVE_RXDMA
+static void imxrt_dma_rxint(struct uart_dev_s *dev, bool enable)
+{
+  struct imxrt_uart_s *priv = (struct imxrt_uart_s *)dev;
+
+  /* Enable/disable DMA reception.
+   *
+   * Note that it is not safe to check for available bytes and immediately
+   * pass them to uart_recvchars as that could potentially recurse back
+   * to us again.  Instead, bytes must wait until the next up_dma_poll or
+   * DMA event.
+   */
+
+  priv->rxenable = enable;
+}
+#endif
+
+/****************************************************************************
+ * Name: imxrt_dma_rxavailable
+ *
+ * Description:
+ *   Return true if the receive register is not empty
+ *
+ ****************************************************************************/
+
+#ifdef SERIAL_HAVE_RXDMA
+static bool imxrt_dma_rxavailable(struct uart_dev_s *dev)
+{
+  struct imxrt_uart_s *priv = (struct imxrt_uart_s *)dev;
+
+  /* Compare our receive pointer to the current DMA pointer, if they
+   * do not match, then there are bytes to be received.
+   */
+
+  return (imxrt_dma_nextrx(priv) != priv->rxdmanext);
+}
+#endif
+
+/****************************************************************************
+ * Name: imxrt_dma_txcallback
+ *
+ * Description:
+ *   This function clears dma buffer at complete of DMA transfer and wakes up
+ *   threads waiting for space in buffer.
+ *
+ ****************************************************************************/
+
+#ifdef SERIAL_HAVE_TXDMA
+static void imxrt_dma_txcallback(DMACH_HANDLE handle, void *arg, bool done,
+                                  int result)
+{
+  struct imxrt_uart_s *priv = (struct imxrt_uart_s *)arg;
+  /* Update 'nbytes' indicating number of bytes actually transferred by DMA.
+   * This is important to free TX buffer space by 'uart_xmitchars_done'.
+   */
+
+  priv->dev.dmatx.nbytes = priv->dev.dmatx.length + priv->dev.dmatx.nlength;
+
+  /* Adjust the pointers */
+
+  uart_xmitchars_done(&priv->dev);
+
+  /* Release waiter */
+
+  nxsem_post(&priv->txdmasem);
+}
+#endif
+
+/****************************************************************************
+ * Name: imxrt_dma_txavailable
+ *
+ * Description:
+ *        Informs DMA that Tx data is available and is ready for transfer.
+ *
+ ****************************************************************************/
+
+#ifdef SERIAL_HAVE_TXDMA
+static void imxrt_dma_txavailable(struct uart_dev_s *dev)
+{
+  struct imxrt_uart_s *priv = (struct imxrt_uart_s *)dev;
+
+  /* Only send when the DMA is idle */
+
+  nxsem_wait(&priv->txdmasem);
+
+  uart_xmitchars_dma(dev);
+}
+#endif
+
+/****************************************************************************
+ * Name: imxrt_dma_send
+ *
+ * Description:
+ *   Called (usually) from the interrupt level to start DMA transfer.
+ *   (Re-)Configures DMA Stream updating buffer and buffer length.
+ *
+ ****************************************************************************/
+
+#ifdef SERIAL_HAVE_TXDMA
+static void imxrt_dma_send(struct uart_dev_s *dev)
+{
+  struct imxrt_uart_s *priv = (struct imxrt_uart_s *)dev;
+  struct imxrt_edma_xfrconfig_s config;
+
+  /* We need to stop DMA before reconfiguration */
+
+  imxrt_dmach_stop(priv->txdma);
+
+  /* Reset the number sent */
+
+  dev->dmatx.nbytes = 0;
+
+  /* Make use of setup function to update buffer and its length for next
+   * transfer
+   */
+
+  config.iter   = dev->dmatx.length;
+  config.flags  = EDMA_CONFIG_LINKTYPE_LINKNONE;
+  config.ssize  = EDMA_8BIT;
+  config.dsize  = EDMA_8BIT;
+  config.nbytes = sizeof(dev->dmatx.buffer[0]);
+  config.saddr  = (uint32_t) dev->dmatx.buffer;
+  config.daddr  = priv->uartbase + IMXRT_LPUART_DATA_OFFSET;
+  config.soff   = sizeof(dev->dmatx.buffer[0]);
+  config.doff   = 0;
+#ifdef CONFIG_IMXRT_EDMA_ELINK
+  config.linkch  = 0;
+#endif
+
+  /* Flush the contents of the TX buffer into physical memory */
+
+  up_clean_dcache((uintptr_t)dev->dmatx.buffer,
+                  (uintptr_t)dev->dmatx.buffer + dev->dmatx.length);
+
+  /* Setup first half */
+
+  imxrt_dmach_xfrsetup(priv->txdma, &config);
+
+  /* Is this a split transfer? */
+
+  if (dev->dmatx.nbuffer)
+    {
+      config.iter   = priv->dev.dmatx.nlength;
+      config.saddr  = (uint32_t) priv->dev.dmatx.nbuffer;
+
+      /* Flush the contents of the next TX buffer into physical memory */
+
+      up_clean_dcache((uintptr_t)dev->dmatx.nbuffer,
+                      (uintptr_t)dev->dmatx.nbuffer + dev->dmatx.nlength);
+
+      imxrt_dmach_xfrsetup(priv->txdma, &config);
+    }
+
+  /* Start transmission with the callback on DMA completion */
+
+  imxrt_dmach_start(priv->txdma, imxrt_dma_txcallback, (void *)priv);
+}
+#endif
 
 /****************************************************************************
  * Name: imxrt_send
@@ -1505,10 +2579,32 @@ static bool imxrt_rxavailable(struct uart_dev_s *dev)
 
 static void imxrt_send(struct uart_dev_s *dev, int ch)
 {
-  struct imxrt_uart_s *priv = (struct imxrt_uart_s *)dev->priv;
+  struct imxrt_uart_s *priv = (struct imxrt_uart_s *)dev;
   imxrt_serialout(priv, IMXRT_LPUART_DATA_OFFSET, (uint32_t)ch);
 }
 
+/****************************************************************************
+ * Name: imxrt_dma_txint
+ *
+ * Description:
+ *   Call to enable or disable TX interrupts from the UART.
+ *
+ ****************************************************************************/
+
+#ifdef SERIAL_HAVE_TXDMA
+static void imxrt_dma_txint(struct uart_dev_s *dev, bool enable)
+{
+  /* Nothing to do. */
+
+  /* In case of DMA transfer we do not want to make use of UART interrupts.
+   * Instead, we use DMA interrupts that are activated once during boot
+   * sequence. Furthermore we can use imxrt_dma_txcallback() to handle stuff
+   * at half DMA transfer or after transfer completion (depending on the
+   *  configuration).
+   */
+}
+#endif
+
 /****************************************************************************
  * Name: imxrt_txint
  *
@@ -1517,9 +2613,10 @@ static void imxrt_send(struct uart_dev_s *dev, int ch)
  *
  ****************************************************************************/
 
+#if !defined(SERIAL_HAVE_ONLY_TXDMA)
 static void imxrt_txint(struct uart_dev_s *dev, bool enable)
 {
-  struct imxrt_uart_s *priv = (struct imxrt_uart_s *)dev->priv;
+  struct imxrt_uart_s *priv = (struct imxrt_uart_s *)dev;
   irqstate_t flags;
   uint32_t regval;
 
@@ -1543,6 +2640,7 @@ static void imxrt_txint(struct uart_dev_s *dev, bool enable)
   imxrt_serialout(priv, IMXRT_LPUART_CTRL_OFFSET, regval);
   spin_unlock_irqrestore(NULL, flags);
 }
+#endif
 
 /****************************************************************************
  * Name: imxrt_txready
@@ -1554,7 +2652,7 @@ static void imxrt_txint(struct uart_dev_s *dev, bool enable)
 
 static bool imxrt_txready(struct uart_dev_s *dev)
 {
-  struct imxrt_uart_s *priv = (struct imxrt_uart_s *)dev->priv;
+  struct imxrt_uart_s *priv = (struct imxrt_uart_s *)dev;
   uint32_t regval;
 
   regval = imxrt_serialin(priv, IMXRT_LPUART_STAT_OFFSET);
@@ -1571,13 +2669,58 @@ static bool imxrt_txready(struct uart_dev_s *dev)
 
 static bool imxrt_txempty(struct uart_dev_s *dev)
 {
-  struct imxrt_uart_s *priv = (struct imxrt_uart_s *)dev->priv;
+  struct imxrt_uart_s *priv = (struct imxrt_uart_s *)dev;
   uint32_t regval;
 
   regval = imxrt_serialin(priv, IMXRT_LPUART_STAT_OFFSET);
   return ((regval & LPUART_STAT_TC) != 0);
 }
 
+/****************************************************************************
+ * Name: imxrt_dma_rxcallback
+ *
+ * Description:
+ *   This function checks the current DMA state and calls the generic
+ *   serial stack when bytes appear to be available.
+ *
+ ****************************************************************************/
+
+#ifdef SERIAL_HAVE_RXDMA
+static void imxrt_dma_rxcallback(DMACH_HANDLE handle, void *arg, bool done,
+                                  int result)
+{
+  struct imxrt_uart_s *priv = (struct imxrt_uart_s *)arg;
+  uint32_t sr;
+
+  up_invalidate_dcache((uintptr_t)priv->rxfifo,
+                       (uintptr_t)priv->rxfifo + RXDMA_BUFFER_SIZE);
+
+  if (priv->rxenable && imxrt_dma_rxavailable(&priv->dev))
+    {
+      uart_recvchars(&priv->dev);
+    }
+
+  /* Get the masked LPUART status word to check and clear error flags.
+   *
+   * When wake-up from low power mode was not fast enough, UART is resumed
+   * too late and sometimes exactly when character was coming over UART,
+   * resulting to frame error.
+   * If error flag is not cleared, Rx DMA will be stuck. Clearing errors
+   * will release Rx DMA.
+   */
+
+  sr = imxrt_serialin(priv, IMXRT_LPUART_STAT_OFFSET);
+
+  if ((sr & (LPUART_STAT_OR | LPUART_STAT_NF | LPUART_STAT_FE)) != 0)
+    {
+      imxrt_serialout(priv, IMXRT_LPUART_STAT_OFFSET,
+                      sr & (LPUART_STAT_OR |
+                            LPUART_STAT_NF |
+                            LPUART_STAT_FE));
+    }
+}
+#endif
+
 /****************************************************************************
  * Name: up_pm_notify
  *
@@ -1708,8 +2851,8 @@ void imxrt_earlyserialinit(void)
    */
 
 #ifdef CONSOLE_DEV
-  CONSOLE_DEV.isconsole = true;
-  imxrt_setup(&CONSOLE_DEV);
+  CONSOLE_DEV.dev.isconsole = true;
+  imxrt_setup(&CONSOLE_DEV.dev);
 #endif
 }
 
@@ -1735,32 +2878,35 @@ void arm_serialinit(void)
 #endif
 
 #ifdef CONSOLE_DEV
-  uart_register("/dev/console", &CONSOLE_DEV);
+  uart_register("/dev/console", &CONSOLE_DEV.dev);
+#if defined(SERIAL_HAVE_CONSOLE_DMA)
+  imxrt_dma_setup(&CONSOLE_DEV.dev);
+#endif
 #endif
 
   /* Register all UARTs */
 
-  uart_register("/dev/ttyS0", &TTYS0_DEV);
+  uart_register("/dev/ttyS0", &TTYS0_DEV.dev);
 #ifdef TTYS1_DEV
-  uart_register("/dev/ttyS1", &TTYS1_DEV);
+  uart_register("/dev/ttyS1", &TTYS1_DEV.dev);
 #endif
 #ifdef TTYS2_DEV
-  uart_register("/dev/ttyS2", &TTYS2_DEV);
+  uart_register("/dev/ttyS2", &TTYS2_DEV.dev);
 #endif
 #ifdef TTYS3_DEV
-  uart_register("/dev/ttyS3", &TTYS3_DEV);
+  uart_register("/dev/ttyS3", &TTYS3_DEV.dev);
 #endif
 #ifdef TTYS4_DEV
-  uart_register("/dev/ttyS4", &TTYS4_DEV);
+  uart_register("/dev/ttyS4", &TTYS4_DEV.dev);
 #endif
 #ifdef TTYS5_DEV
-  uart_register("/dev/ttyS5", &TTYS5_DEV);
+  uart_register("/dev/ttyS5", &TTYS5_DEV.dev);
 #endif
 #ifdef TTYS6_DEV
-  uart_register("/dev/ttyS6", &TTYS6_DEV);
+  uart_register("/dev/ttyS6", &TTYS6_DEV.dev);
 #endif
 #ifdef TTYS7_DEV
-  uart_register("/dev/ttyS7", &TTYS7_DEV);
+  uart_register("/dev/ttyS7", &TTYS7_DEV.dev);
 #endif
 }
 
@@ -1775,7 +2921,7 @@ void arm_serialinit(void)
 int up_putc(int ch)
 {
 #ifdef CONSOLE_DEV
-  struct imxrt_uart_s *priv = (struct imxrt_uart_s *)CONSOLE_DEV.priv;
+  struct imxrt_uart_s *priv = (struct imxrt_uart_s *)CONSOLE_DEV.dev.priv;
   uint32_t ie;
 
   imxrt_disableuartint(priv, &ie);
diff --git a/arch/arm/src/imxrt/imxrt_serial.h b/arch/arm/src/imxrt/imxrt_serial.h
index 102c570702..7b608baafb 100644
--- a/arch/arm/src/imxrt/imxrt_serial.h
+++ b/arch/arm/src/imxrt/imxrt_serial.h
@@ -34,6 +34,190 @@
  * Pre-processor Definitions
  ****************************************************************************/
 
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#if defined(CONFIG_IMXRT_LPUART1) || defined(CONFIG_IMXRT_LPUART2) || \
+    defined(CONFIG_IMXRT_LPUART3) || defined(CONFIG_IMXRT_LPUART4) || \
+    defined(CONFIG_IMXRT_LPUART5) || defined(CONFIG_IMXRT_LPUART6) || \
+    defined(CONFIG_IMXRT_LPUART7) || defined(CONFIG_IMXRT_LPUART8)
+#  define HAVE_UART 1
+#endif
+
+/* Assume DMA is not used on the console UART */
+
+#undef SERIAL_HAVE_CONSOLE_RXDMA
+#undef SERIAL_HAVE_CONSOLE_TXDMA
+
+#if !defined(HAVE_UART) || !defined(CONFIG_ARCH_DMA)
+#  undef CONFIG_LPUART1_RXDMA
+#  undef CONFIG_LPUART1_TXDMA
+#  undef CONFIG_LPUART2_RXDMA
+#  undef CONFIG_LPUART2_TXDMA
+#  undef CONFIG_LPUART3_RXDMA
+#  undef CONFIG_LPUART3_TXDMA
+#  undef CONFIG_LPUART4_RXDMA
+#  undef CONFIG_LPUART4_TXDMA
+#  undef CONFIG_LPUART5_RXDMA
+#  undef CONFIG_LPUART5_TXDMA
+#  undef CONFIG_LPUART6_RXDMA
+#  undef CONFIG_LPUART6_TXDMA
+#  undef CONFIG_LPUART7_RXDMA
+#  undef CONFIG_LPUART7_TXDMA
+#  undef CONFIG_LPUART8_RXDMA
+#  undef CONFIG_LPUART8_TXDMA
+#endif
+
+/* Disable the DMA configuration on all unused LPUARTs */
+
+#ifndef CONFIG_IMXRT_LPUART1
+#  undef CONFIG_LPUART1_RXDMA
+#  undef CONFIG_LPUART1_TXDMA
+#endif
+
+#ifndef CONFIG_IMXRT_LPUART2
+#  undef CONFIG_LPUART2_RXDMA
+#  undef CONFIG_LPUART2_TXDMA
+#endif
+
+#ifndef CONFIG_IMXRT_LPUART3
+#  undef CONFIG_LPUART3_RXDMA
+#  undef CONFIG_LPUART3_TXDMA
+#endif
+
+#ifndef CONFIG_IMXRT_LPUART4
+#  undef CONFIG_LPUART4_RXDMA
+#  undef CONFIG_LPUART4_TXDMA
+#endif
+
+#ifndef CONFIG_IMXRT_LPUART5
+#  undef CONFIG_LPUART5_RXDMA
+#  undef CONFIG_LPUART5_TXDMA
+#endif
+
+#ifndef CONFIG_IMXRT_LPUART6
+#  undef CONFIG_LPUART6_RXDMA
+#  undef CONFIG_LPUART6_TXDMA
+#endif
+
+#ifndef CONFIG_IMXRT_LPUART7
+#  undef CONFIG_LPUART7_RXDMA
+#  undef CONFIG_LPUART7_TXDMA
+#endif
+
+#ifndef CONFIG_IMXRT_LPUART8
+#  undef CONFIG_LPUART8_RXDMA
+#  undef CONFIG_LPUART8_TXDMA
+#endif
+
+/* Is RX DMA available on any (enabled) LPUART? */
+
+#undef SERIAL_HAVE_RXDMA
+#if defined(CONFIG_LPUART1_RXDMA) || defined(CONFIG_LPUART2_RXDMA) || \
+    defined(CONFIG_LPUART3_RXDMA) || defined(CONFIG_LPUART4_RXDMA) || \
+    defined(CONFIG_LPUART5_RXDMA) || defined(CONFIG_LPUART6_RXDMA) || \
+    defined(CONFIG_LPUART7_RXDMA) || defined(CONFIG_LPUART8_RXDMA)
+#  define SERIAL_HAVE_RXDMA 1
+#endif
+
+/* Is TX DMA available on any (enabled) LPUART? */
+#undef SERIAL_HAVE_TXDMA
+#if defined(CONFIG_LPUART1_TXDMA) || defined(CONFIG_LPUART2_TXDMA) || \
+    defined(CONFIG_LPUART3_TXDMA) || defined(CONFIG_LPUART4_TXDMA) || \
+    defined(CONFIG_LPUART5_TXDMA) || defined(CONFIG_LPUART6_TXDMA) || \
+    defined(CONFIG_LPUART7_TXDMA) || defined(CONFIG_LPUART8_TXDMA)
+#  define SERIAL_HAVE_TXDMA 1
+#endif
+
+/* Is RX DMA used on all (enabled) LPUARTs */
+
+#define SERIAL_HAVE_ONLY_RXDMA 1
+#if defined(CONFIG_IMXRT_LPUART1) && !defined(CONFIG_LPUART1_RXDMA)
+#  undef SERIAL_HAVE_ONLY_RXDMA
+#elif defined(CONFIG_IMXRT_LPUART2) && !defined(CONFIG_LPUART2_RXDMA)
+#  undef SERIAL_HAVE_ONLY_RXDMA
+#elif defined(CONFIG_IMXRT_LPUART3) && !defined(CONFIG_LPUART3_RXDMA)
+#  undef SERIAL_HAVE_ONLY_RXDMA
+#elif defined(CONFIG_IMXRT_LPUART4) && !defined(CONFIG_LPUART4_RXDMA)
+#  undef SERIAL_HAVE_ONLY_RXDMA
+#elif defined(CONFIG_IMXRT_LPUART5) && !defined(CONFIG_LPUART5_RXDMA)
+#  undef SERIAL_HAVE_ONLY_RXDMA
+#elif defined(CONFIG_IMXRT_LPUART6) && !defined(CONFIG_LPUART6_RXDMA)
+#  undef SERIAL_HAVE_ONLY_RXDMA
+#elif defined(CONFIG_IMXRT_LPUART7) && !defined(CONFIG_LPUART7_RXDMA)
+#  undef SERIAL_HAVE_ONLY_RXDMA
+#elif defined(CONFIG_IMXRT_LPUART8) && !defined(CONFIG_LPUART8_RXDMA)
+#  undef SERIAL_HAVE_ONLY_RXDMA
+#endif
+
+/* Is TX DMA used on all (enabled) LPUARTs */
+
+#define SERIAL_HAVE_ONLY_TXDMA 1
+#if defined(CONFIG_IMXRT_LPUART1) && !defined(CONFIG_LPUART1_TXDMA)
+#  undef SERIAL_HAVE_ONLY_TXDMA
+#elif defined(CONFIG_IMXRT_LPUART2) && !defined(CONFIG_LPUART2_TXDMA)
+#  undef SERIAL_HAVE_ONLY_TXDMA
+#elif defined(CONFIG_IMXRT_LPUART3) && !defined(CONFIG_LPUART3_TXDMA)
+#  undef SERIAL_HAVE_ONLY_TXDMA
+#elif defined(CONFIG_IMXRT_LPUART4) && !defined(CONFIG_LPUART4_TXDMA)
+#  undef SERIAL_HAVE_ONLY_TXDMA
+#elif defined(CONFIG_IMXRT_LPUART5) && !defined(CONFIG_LPUART5_TXDMA)
+#  undef SERIAL_HAVE_ONLY_TXDMA
+#elif defined(CONFIG_IMXRT_LPUART6) && !defined(CONFIG_LPUART6_TXDMA)
+#  undef SERIAL_HAVE_ONLY_TXDMA
+#elif defined(CONFIG_IMXRT_LPUART7) && !defined(CONFIG_LPUART7_TXDMA)
+#  undef SERIAL_HAVE_ONLY_TXDMA
+#elif defined(CONFIG_IMXRT_LPUART8) && !defined(CONFIG_LPUART8_TXDMA)
+#  undef SERIAL_HAVE_ONLY_TXDMA
+#endif
+
+#undef SERIAL_HAVE_ONLY_DMA
+#if defined(SERIAL_HAVE_ONLY_RXDMA) && defined(SERIAL_HAVE_ONLY_TXDMA)
+#define SERIAL_HAVE_ONLY_DMA
+#endif
+
+/* Verify that DMA has been enabled and the DMA channel has been defined.
+ */
+
+#  if defined(SERIAL_HAVE_TXDMA) || defined(SERIAL_HAVE_RXDMA)
+#    ifndef CONFIG_IMXRT_EDMA
+#      error IMXRT LPUART receive or transmit DMA requires CONFIG_IMXRT_EDMA
+#    endif
+#  endif
+
+#if defined(SERIAL_HAVE_RXDMA)
+/* Currently RS-485 support cannot be enabled when RXDMA is in use due to
+ * lack of testing.
+ */
+
+#  if (defined(CONFIG_LPUART1_RXDMA) && defined(CONFIG_LPUART1_RS485)) || \
+      (defined(CONFIG_LPUART2_RXDMA) && defined(CONFIG_LPUART2_RS485)) || \
+      (defined(CONFIG_LPUART3_RXDMA) && defined(CONFIG_LPUART3_RS485)) || \
+      (defined(CONFIG_LPUART4_RXDMA) && defined(CONFIG_LPUART4_RS485)) || \
+      (defined(CONFIG_LPUART5_RXDMA) && defined(CONFIG_LPUART5_RS485)) || \
+      (defined(CONFIG_LPUART6_RXDMA) && defined(CONFIG_LPUART6_RS485)) || \
+      (defined(CONFIG_LPUART7_RXDMA) && defined(CONFIG_LPUART7_RS485)) || \
+      (defined(CONFIG_LPUART8_RXDMA) && defined(CONFIG_LPUART8_RS485))
+#    error "RXDMA and RS-485 cannot be enabled at the same time for the same LPUART"
+#  endif
+#endif /* SERIAL_HAVE_RXDMA */
+
+/* Currently RS-485 support cannot be enabled when TXDMA is in use due to
+ * lack of testing.
+ */
+
+#if (defined(CONFIG_LPUART1_TXDMA) && defined(CONFIG_LPUART1_RS485)) || \
+    (defined(CONFIG_LPUART2_TXDMA) && defined(CONFIG_LPUART2_RS485)) || \
+    (defined(CONFIG_LPUART3_TXDMA) && defined(CONFIG_LPUART3_RS485)) || \
+    (defined(CONFIG_LPUART4_TXDMA) && defined(CONFIG_LPUART4_RS485)) || \
+    (defined(CONFIG_LPUART5_TXDMA) && defined(CONFIG_LPUART5_RS485)) || \
+    (defined(CONFIG_LPUART6_TXDMA) && defined(CONFIG_LPUART6_RS485)) || \
+    (defined(CONFIG_LPUART7_TXDMA) && defined(CONFIG_LPUART7_RS485)) || \
+    (defined(CONFIG_LPUART8_TXDMA) && defined(CONFIG_LPUART8_RS485))
+#  error "TXDMA and RS-485 cannot be enabled at the same time for the same LPUART"
+#endif
+
 /****************************************************************************
  * Public Types
  ****************************************************************************/


[incubator-nuttx] 04/04: imxrt:SPI add DMA support

Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 55aaba53fc735d645332703efdc72310dd56cc86
Author: David Sidrane <Da...@NscDg.com>
AuthorDate: Thu Jul 21 05:40:31 2022 -0700

    imxrt:SPI add DMA support
---
 arch/arm/src/imxrt/Kconfig       |  49 +++++
 arch/arm/src/imxrt/imxrt_lpspi.c | 416 +++++++++++++++++++++++++++++++++++++--
 2 files changed, 445 insertions(+), 20 deletions(-)

diff --git a/arch/arm/src/imxrt/Kconfig b/arch/arm/src/imxrt/Kconfig
index b8608c1511..cf5d387096 100644
--- a/arch/arm/src/imxrt/Kconfig
+++ b/arch/arm/src/imxrt/Kconfig
@@ -1809,6 +1809,55 @@ config IMXRT_EDMA_EDBG
 
 endmenu # eDMA Global Configuration
 
+menu "LPSPI Configuration"
+	depends on IMXRT_LPSPI
+
+config IMXRT_LPSPI_DMA
+	bool "LPSPI DMA"
+	depends on IMXRT_EDMA
+	default n
+	---help---
+		Use DMA to improve LPSPI transfer performance.
+
+config IMXRT_LPSPI_DMATHRESHOLD
+	int "LPSPI DMA threshold"
+	default 4
+	depends on IMXRT_LPSPI_DMA
+	---help---
+		When SPI DMA is enabled, small DMA transfers will still be performed
+		by polling logic.  But we need a threshold value to determine what
+		is small.
+
+config IMXRT_LPSPI1_DMA
+	bool "LPSPI1 DMA"
+	default n
+	depends on IMXRT_LPSPI1 && IMXRT_LPSPI_DMA
+	---help---
+		Use DMA to improve LPSPI1 transfer performance.
+
+config IMXRT_LPSPI2_DMA
+	bool "LPSPI2 DMA"
+	default n
+	depends on IMXRT_LPSPI2 && IMXRT_LPSPI_DMA
+	---help---
+		Use DMA to improve LPSPI2 transfer performance.
+
+config IMXRT_LPSPI3_DMA
+	bool "LPSPI3 DMA"
+	default n
+	depends on IMXRT_LPSPI3 && IMXRT_LPSPI_DMA
+	---help---
+		Use DMA to improve LPSPI3 transfer performance.
+
+config IMXRT_LPSPI4_DMA
+	bool "LPSPI4 DMA"
+	default n
+	depends on IMXRT_LPSPI4 && IMXRT_LPSPI_DMA
+	---help---
+		Use DMA to improve SPI4 transfer performance.
+
+endmenu # LPSPI Configuration
+
 if PM
 
 config IMXRT_PM_SERIAL_ACTIVITY
diff --git a/arch/arm/src/imxrt/imxrt_lpspi.c b/arch/arm/src/imxrt/imxrt_lpspi.c
index e8afad3928..32a338a10f 100644
--- a/arch/arm/src/imxrt/imxrt_lpspi.c
+++ b/arch/arm/src/imxrt/imxrt_lpspi.c
@@ -74,6 +74,9 @@
 #include "hardware/imxrt_ccm.h"
 #include "imxrt_periphclks.h"
 
+#include "hardware/imxrt_dmamux.h"
+#include "imxrt_edma.h"
+
 #if defined(CONFIG_IMXRT_LPSPI1) || defined(CONFIG_IMXRT_LPSPI2) || \
     defined(CONFIG_IMXRT_LPSPI3) || defined(CONFIG_IMXRT_LPSPI4)
 
@@ -89,16 +92,15 @@
 #  error "Interrupt driven SPI not yet supported"
 #endif
 
-#if defined(CONFIG_IMXRT_LPSPI_DMA)
-#  error "DMA mode is not yet supported"
-#endif
-
 /* Can't have both interrupt driven SPI and SPI DMA */
 
 #if defined(CONFIG_IMXRT_LPSPI_INTERRUPTS) && defined(CONFIG_IMXRT_LPSPI_DMA)
 #  error "Cannot enable both interrupt mode and DMA mode for SPI"
 #endif
 
+#define  SPI_SR_CLEAR   (LPSPI_SR_WCF | LPSPI_SR_FCF | LPSPI_SR_TCF  | \
+                         LPSPI_SR_TEF | LPSPI_SR_REF | LPSPI_SR_DMF)
+
 /****************************************************************************
  * Private Types
  ****************************************************************************/
@@ -115,6 +117,16 @@ struct imxrt_lpspidev_s
   uint32_t actual;            /* Actual clock frequency */
   int8_t nbits;               /* Width of word in bits */
   uint8_t mode;               /* Mode 0,1,2,3 */
+#ifdef CONFIG_IMXRT_LPSPI_DMA
+  volatile uint32_t rxresult;   /* Result of the RX DMA */
+  volatile uint32_t txresult;   /* Result of the TX DMA */
+  const uint16_t    rxch;       /* The RX DMA channel number */
+  const uint16_t    txch;       /* The TX DMA channel number */
+  DMACH_HANDLE      rxdma;      /* DMA channel handle for RX transfers */
+  DMACH_HANDLE      txdma;      /* DMA channel handle for TX transfers */
+  sem_t             rxsem;      /* Wait for RX DMA to complete */
+  sem_t             txsem;      /* Wait for TX DMA to complete */
+#endif
 };
 
 enum imxrt_delay_e
@@ -149,6 +161,21 @@ static inline void imxrt_lpspi_master_set_delay_scaler(
                           uint32_t scaler,
                           enum imxrt_delay_e type);
 
+/* DMA support */
+
+#ifdef CONFIG_IMXRT_LPSPI_DMA
+static int         spi_dmarxwait(FAR struct imxrt_lpspidev_s *priv);
+static int         spi_dmatxwait(FAR struct imxrt_lpspidev_s *priv);
+static inline void spi_dmarxwakeup(FAR struct imxrt_lpspidev_s *priv);
+static inline void spi_dmatxwakeup(FAR struct imxrt_lpspidev_s *priv);
+static void        spi_dmarxcallback(DMACH_HANDLE handle, void *arg,
+                                     bool done, int result);
+static void        spi_dmatxcallback(DMACH_HANDLE handle, void *arg,
+                                     bool done, int result);
+static inline void spi_dmarxstart(FAR struct imxrt_lpspidev_s *priv);
+static inline void spi_dmatxstart(FAR struct imxrt_lpspidev_s *priv);
+#endif
+
 /* SPI methods */
 
 static int imxrt_lpspi_lock(struct spi_dev_s *dev, bool lock);
@@ -221,9 +248,9 @@ static struct imxrt_lpspidev_s g_lpspi1dev =
 #ifdef CONFIG_IMXRT_LPSPI_INTERRUPTS
   .spiirq       = IMXRT_IRQ_LPSPI1,
 #endif
-#ifdef CONFIG_IMXRT_LPSPI_DMA
-  .rxch         = DMAMAP_LPSPI1_RX,
-  .txch         = DMAMAP_LPSPI1_TX,
+#ifdef CONFIG_IMXRT_LPSPI1_DMA
+  .rxch         = IMXRT_DMACHAN_LPSPI1_RX,
+  .txch         = IMXRT_DMACHAN_LPSPI1_TX,
 #endif
 };
 #endif
@@ -267,9 +294,9 @@ static struct imxrt_lpspidev_s g_lpspi2dev =
 #ifdef CONFIG_IMXRT_LPSPI_INTERRUPTS
   .spiirq       = IMXRT_IRQ_LPSPI2,
 #endif
-#ifdef CONFIG_IMXRT_LPSPI_DMA
-  .rxch         = DMAMAP_LPSPI2_RX,
-  .txch         = DMAMAP_LPSPI2_TX,
+#ifdef CONFIG_IMXRT_LPSPI2_DMA
+  .rxch         = IMXRT_DMACHAN_LPSPI2_RX,
+  .txch         = IMXRT_DMACHAN_LPSPI2_TX,
 #endif
 };
 #endif
@@ -313,9 +340,9 @@ static struct imxrt_lpspidev_s g_lpspi3dev =
 #ifdef CONFIG_IMXRT_LPSPI_INTERRUPTS
   .spiirq       = IMXRT_IRQ_LPSPI3,
 #endif
-#ifdef CONFIG_IMXRT_LPSPI_DMA
-  .rxch         = DMAMAP_LPSPI3_RX,
-  .txch         = DMAMAP_LPSPI3_TX,
+#ifdef CONFIG_IMXRT_LPSPI3_DMA
+  .rxch         = IMXRT_DMACHAN_LPSPI3_RX,
+  .txch         = IMXRT_DMACHAN_LPSPI3_TX,
 #endif
 };
 #endif
@@ -359,9 +386,9 @@ static struct imxrt_lpspidev_s g_lpspi4dev =
 #ifdef CONFIG_IMXRT_LPSPI_INTERRUPTS
   .spiirq       = IMXRT_IRQ_LPSPI4,
 #endif
-#ifdef CONFIG_IMXRT_LPSPI_DMA
-  .rxch         = DMAMAP_LPSPI4_RX,
-  .txch         = DMAMAP_LPSPI4_TX,
+#ifdef CONFIG_IMXRT_LPSPI4_DMA
+  .rxch         = IMXRT_DMACHAN_LPSPI4_RX,
+  .txch         = IMXRT_DMACHAN_LPSPI4_TX,
 #endif
 };
 #endif
@@ -596,7 +623,7 @@ imxrt_lpspi_9to16bitmode(struct imxrt_lpspidev_s *priv)
 }
 
 /****************************************************************************
- * Name: imxrt_lpspi_modifyreg
+ * Name: imxrt_lpspi_modifyreg32
  *
  * Description:
  *   Clear and set bits in register
@@ -1269,7 +1296,6 @@ static uint32_t imxrt_lpspi_send(struct spi_dev_s *dev, uint32_t wd)
  *
  ****************************************************************************/
 
-#if !defined(CONFIG_IMXRT_LPSPI_DMA) || defined(CONFIG_IMXRT_DMACAPABLE)
 #if !defined(CONFIG_IMXRT_LPSPI_DMA)
 static void imxrt_lpspi_exchange(struct spi_dev_s *dev,
                                  const void *txbuffer,
@@ -1355,7 +1381,159 @@ static void imxrt_lpspi_exchange_nodma(struct spi_dev_s *dev,
         }
     }
 }
-#endif /* !CONFIG_IMXRT_LPSPI_DMA || CONFIG_IMXRT_DMACAPABLE */
+
+/****************************************************************************
+ * Name: spi_exchange (with DMA capability)
+ *
+ * Description:
+ *   Exchange a block of data on SPI using DMA
+ *
+ * Input Parameters:
+ *   dev      - Device-specific state data
+ *   txbuffer - A pointer to the buffer of data to be sent
+ *   rxbuffer - A pointer to a buffer in which to receive data
+ *   nwords   - the length of data 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_IMXRT_LPSPI_DMA
+static void imxrt_lpspi_exchange(FAR struct spi_dev_s * dev,
+                                   FAR const void * txbuffer,
+                                   FAR void * rxbuffer, size_t nwords)
+{
+  int                          ret;
+  size_t                       adjust;
+  ssize_t                      nbytes;
+  static uint8_t               rxdummy[4] aligned_data(4);
+  static const uint16_t        txdummy = 0xffff;
+  uint32_t                     regval;
+  FAR struct imxrt_lpspidev_s *priv = (FAR struct imxrt_lpspidev_s *)dev;
+
+  DEBUGASSERT(priv != NULL);
+  DEBUGASSERT(priv && priv->spibase);
+  spiinfo("txbuffer=%p rxbuffer=%p nwords=%d\n", txbuffer, rxbuffer, nwords);
+
+  /* Convert the number of word to a number of bytes */
+
+  nbytes = (priv->nbits > 8) ? nwords << 2 : nwords;
+
+  /* Invalid DMA channels fall back to non-DMA method. */
+
+  if (priv->rxdma == NULL || priv->txdma == NULL
+#ifdef CONFIG_IMXRT_LPSPI_DMATHRESHOLD
+      /* If this is a small SPI transfer, then let
+       * imxrt_lpspi_exchange_nodma() do the work.
+       */
+
+      || nbytes <= CONFIG_IMXRT_LPSPI_DMATHRESHOLD
+#endif
+      )
+    {
+      imxrt_lpspi_exchange_nodma(dev, txbuffer, rxbuffer, nwords);
+      return;
+    }
+
+  /* ERR050456 workaround: Reset FIFOs using CR[RST] bit */
+
+  regval = imxrt_lpspi_getreg32(priv, IMXRT_LPSPI_CFGR1_OFFSET);
+
+  imxrt_lpspi_modifyreg32(priv, IMXRT_LPSPI_CR_OFFSET,
+                LPSPI_CR_RTF | LPSPI_CR_RRF,
+                LPSPI_CR_RTF | LPSPI_CR_RRF);
+
+  imxrt_lpspi_putreg32(priv, IMXRT_LPSPI_CFGR1_OFFSET, regval);
+
+  /* Clear all status bits */
+
+  imxrt_lpspi_putreg32(priv, IMXRT_LPSPI_SR_OFFSET, SPI_SR_CLEAR);
+
+  /* disable DMA */
+
+  imxrt_lpspi_putreg32(priv, IMXRT_LPSPI_DER_OFFSET, 0);
+
+  if (txbuffer)
+    {
+      up_clean_dcache((uintptr_t)txbuffer, (uintptr_t)txbuffer + nbytes);
+    }
+
+  if (rxbuffer)
+    {
+     up_invalidate_dcache((uintptr_t)rxbuffer,
+                          (uintptr_t)rxbuffer + nbytes);
+    }
+
+  /* Set up the DMA */
+
+  adjust = (priv->nbits > 8) ? 2 : 1;
+
+  struct imxrt_edma_xfrconfig_s config;
+
+  config.saddr  = priv->spibase + IMXRT_LPSPI_RDR_OFFSET;
+  config.daddr  = (uint32_t) (rxbuffer ? rxbuffer : rxdummy);
+  config.soff   = 0;
+  config.doff   = rxbuffer ? adjust : 0;
+  config.iter   = nbytes;
+  config.flags  = EDMA_CONFIG_LINKTYPE_LINKNONE;
+  config.ssize  = adjust == 1 ? EDMA_8BIT : EDMA_16BIT;
+  config.dsize  = adjust == 1 ? EDMA_8BIT : EDMA_16BIT;
+  config.nbytes = adjust;
+#ifdef CONFIG_KINETIS_EDMA_ELINK
+  config.linkch = NULL;
+#endif
+  imxrt_dmach_xfrsetup(priv->rxdma, &config);
+
+  config.saddr  = (uint32_t) (txbuffer ? txbuffer : &txdummy);
+  config.daddr  = priv->spibase + IMXRT_LPSPI_TDR_OFFSET;
+  config.soff   = txbuffer ? adjust : 0;
+  config.doff   = 0;
+  config.iter   = nbytes;
+  config.flags  = EDMA_CONFIG_LINKTYPE_LINKNONE;
+  config.ssize  = adjust == 1 ? EDMA_8BIT : EDMA_16BIT;
+  config.dsize  = adjust == 1 ? EDMA_8BIT : EDMA_16BIT;
+  config.nbytes = adjust;
+#ifdef CONFIG_KINETIS_EDMA_ELINK
+  config.linkch = NULL;
+#endif
+  imxrt_dmach_xfrsetup(priv->txdma, &config);
+
+  /* Start the DMAs */
+
+  spi_dmarxstart(priv);
+  spi_dmatxstart(priv);
+
+  /* Invoke SPI DMA */
+
+  imxrt_lpspi_modifyreg32(priv, IMXRT_LPSPI_DER_OFFSET,
+                0, LPSPI_DER_TDDE | LPSPI_DER_RDDE);
+
+  /* Then wait for each to complete */
+
+  ret = spi_dmarxwait(priv);
+
+  if (ret < 0)
+    {
+      ret = spi_dmatxwait(priv);
+    }
+
+  /* Reset any status */
+
+  imxrt_lpspi_putreg32(priv, IMXRT_LPSPI_SR_OFFSET,
+                         imxrt_lpspi_getreg32(priv,
+                                                IMXRT_LPSPI_SR_OFFSET));
+
+  /* Disable DMA */
+
+  imxrt_lpspi_putreg32(priv, IMXRT_LPSPI_DER_OFFSET, 0);
+}
+
+#endif  /* CONFIG_IMXRT_SPI_DMA */
 
 /****************************************************************************
  * Name: imxrt_lpspi_sndblock
@@ -1542,6 +1720,174 @@ static void imxrt_lpspi_bus_initialize(struct imxrt_lpspidev_s *priv)
   imxrt_lpspi_modifyreg32(priv, IMXRT_LPSPI_CR_OFFSET, 0, LPSPI_CR_MEN);
 }
 
+/****************************************************************************
+ * Name: spi_dmarxwait
+ *
+ * Description:
+ *   Wait for DMA to complete.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_IMXRT_LPSPI_DMA
+static int spi_dmarxwait(FAR struct imxrt_lpspidev_s *priv)
+{
+  int ret;
+
+  /* Take the semaphore (perhaps waiting).  If the result is zero, then the
+   *  DMA must not really have completed.
+   */
+
+  do
+    {
+      ret = nxsem_wait_uninterruptible(&priv->rxsem);
+
+      /* The only expected error is ECANCELED which would occur if the
+       * calling thread were canceled.
+       */
+
+      DEBUGASSERT(ret == OK || ret == -ECANCELED);
+    }
+  while (priv->rxresult == 0 && ret == OK);
+
+  return ret;
+}
+#endif
+
+/****************************************************************************
+ * Name: spi_dmatxwait
+ *
+ * Description:
+ *   Wait for DMA to complete.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_IMXRT_LPSPI_DMA
+static int spi_dmatxwait(FAR struct imxrt_lpspidev_s *priv)
+{
+  int ret;
+
+  /* Take the semaphore (perhaps waiting).  If the result is zero, then the
+   * DMA must not really have completed.
+   */
+
+  do
+    {
+      ret = nxsem_wait_uninterruptible(&priv->txsem);
+
+      /* The only expected error is ECANCELED which would occur if the
+       * calling thread were canceled.
+       */
+
+      DEBUGASSERT(ret == OK || ret == -ECANCELED);
+    }
+  while (priv->txresult == 0 && ret == OK);
+
+  return ret;
+}
+#endif
+
+/****************************************************************************
+ * Name: spi_dmarxwakeup
+ *
+ * Description:
+ *   Signal that DMA is complete
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_IMXRT_LPSPI_DMA
+static inline void spi_dmarxwakeup(FAR struct imxrt_lpspidev_s *priv)
+{
+  nxsem_post(&priv->rxsem);
+}
+#endif
+
+/****************************************************************************
+ * Name: spi_dmatxwakeup
+ *
+ * Description:
+ *   Signal that DMA is complete
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_IMXRT_LPSPI_DMA
+static inline void spi_dmatxwakeup(FAR struct imxrt_lpspidev_s *priv)
+{
+  nxsem_post(&priv->txsem);
+}
+#endif
+
+/****************************************************************************
+ * Name: spi_dmarxcallback
+ *
+ * Description:
+ *   Called when the RX DMA completes
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_IMXRT_LPSPI_DMA
+static void spi_dmarxcallback(DMACH_HANDLE handle, void *arg, bool done,
+                              int result)
+{
+  FAR struct imxrt_lpspidev_s *priv = (FAR struct imxrt_lpspidev_s *)arg;
+
+  priv->rxresult = result | 0x80000000;  /* assure non-zero */
+  spi_dmarxwakeup(priv);
+}
+#endif
+
+/****************************************************************************
+ * Name: spi_dmatxcallback
+ *
+ * Description:
+ *   Called when the RX DMA completes
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_IMXRT_LPSPI_DMA
+static void spi_dmatxcallback(DMACH_HANDLE handle, void *arg, bool done,
+                              int result)
+{
+  FAR struct imxrt_lpspidev_s *priv = (FAR struct imxrt_lpspidev_s *)arg;
+
+  /* Wake-up the SPI driver */
+
+  priv->txresult = result | 0x80000000;  /* assure non-zero */
+  spi_dmatxwakeup(priv);
+}
+#endif
+
+/****************************************************************************
+ * Name: spi_dmarxstart
+ *
+ * Description:
+ *   Start RX DMA
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_IMXRT_LPSPI_DMA
+static inline void spi_dmarxstart(FAR struct imxrt_lpspidev_s *priv)
+{
+  priv->rxresult = 0;
+  imxrt_dmach_start(priv->rxdma, spi_dmarxcallback, priv);
+}
+#endif
+
+/****************************************************************************
+ * Name: spi_dmatxstart
+ *
+ * Description:
+ *   Start TX DMA
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_IMXRT_LPSPI_DMA
+static inline void spi_dmatxstart(FAR struct imxrt_lpspidev_s *priv)
+{
+  priv->txresult = 0;
+  imxrt_dmach_start(priv->txdma, spi_dmatxcallback, priv);
+}
+#endif
+
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
@@ -1694,9 +2040,39 @@ struct spi_dev_s *imxrt_lpspibus_initialize(int bus)
       spierr("ERROR: Unsupported SPI bus: %d\n", bus);
     }
 
+#ifdef CONFIG_IMXRT_LPSPI_DMA
+  /* Initialize the SPI semaphores that is used to wait for DMA completion.
+   * This semaphore is used for signaling and, hence, should not have
+   * priority inheritance enabled.
+   */
+
+  if (priv->rxch && priv->txch)
+    {
+      if (priv->txdma == NULL && priv->rxdma == NULL)
+        {
+          nxsem_init(&priv->rxsem, 0, 0);
+          nxsem_init(&priv->txsem, 0, 0);
+
+          nxsem_set_protocol(&priv->rxsem, SEM_PRIO_NONE);
+          nxsem_set_protocol(&priv->txsem, SEM_PRIO_NONE);
+
+          priv->txdma = imxrt_dmach_alloc(priv->txch | DMAMUX_CHCFG_ENBL,
+                                            0);
+          priv->rxdma = imxrt_dmach_alloc(priv->rxch | DMAMUX_CHCFG_ENBL,
+                                            0);
+          DEBUGASSERT(priv->rxdma && priv->txdma);
+        }
+    }
+  else
+    {
+      priv->rxdma = NULL;
+      priv->txdma = NULL;
+    }
+#endif
+
   leave_critical_section(flags);
 
   return (struct spi_dev_s *)priv;
 }
 
-#endif /* CONFIG_IMXRT_LPSPI1 */
+#endif /* CONFIG_IMXRT_LPSPI1 || CONFIG_IMXRT_LPSPI2 || CONFIG_IMXRT_LPSPI3 || CONFIG_IMXRT_LPSPI4 */


[incubator-nuttx] 01/04: imxrt:lpi2c add parens for macros expansions

Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit f34acdb936bfecdd979b93026e5f81c2139989c0
Author: David Sidrane <Da...@NscDg.com>
AuthorDate: Wed Jun 1 14:00:23 2022 -0700

    imxrt:lpi2c add parens for macros expansions
---
 arch/arm/src/imxrt/hardware/imxrt_lpi2c.h | 60 +++++++++++++++----------------
 1 file changed, 30 insertions(+), 30 deletions(-)

diff --git a/arch/arm/src/imxrt/hardware/imxrt_lpi2c.h b/arch/arm/src/imxrt/hardware/imxrt_lpi2c.h
index 507814cbfa..4e84163486 100644
--- a/arch/arm/src/imxrt/hardware/imxrt_lpi2c.h
+++ b/arch/arm/src/imxrt/hardware/imxrt_lpi2c.h
@@ -301,7 +301,7 @@
 /* LPI2C Master Config Register 1  */
 
 #define LPI2C_MCFGR1_PRESCALE_MASK           (7 << 0)  /* Clock Prescaler Bit Mask */
-#define LPI2C_MCFGR1_PRESCALE(n)             (n & LPI2C_MCFGR1_PRESCALE_MASK)
+#define LPI2C_MCFGR1_PRESCALE(n)             ((n) & LPI2C_MCFGR1_PRESCALE_MASK)
 #  define LPI2C_MCFGR1_PRESCALE_1            (0)
 #  define LPI2C_MCFGR1_PRESCALE_2            (1)
 #  define LPI2C_MCFGR1_PRESCALE_4            (2)
@@ -316,7 +316,7 @@
                                                        /* Bits 15-11 Reserved */
 #define LPI2C_MCFGR1_MATCFG_SHIFT            (16)
 #define LPI2C_MCFGR1_MATCFG_MASK             (7 << LPI2C_MCFGR1_MATCFG_SHIFT)  /* Match Configuration Bit Mask */
-#define LPI2C_MCFGR1_MATCFG(n)               ((n << LPI2C_MCFGR1_MATCFG_SHIFT) & LPI2C_MCFGR1_MATCFG_MASK)
+#define LPI2C_MCFGR1_MATCFG(n)               (((n) << LPI2C_MCFGR1_MATCFG_SHIFT) & LPI2C_MCFGR1_MATCFG_MASK)
 #  define LPI2C_MCFGR1_MATCFG_DISABLE        (0 << LPI2C_MCFGR1_MATCFG_SHIFT)
                                                       /* LPI2C_MCFG1_MATCFG = 001b Reserved */
 #  define LPI2C_MCFGR1_MATCFG2               (2 << LPI2C_MCFGR1_MATCFG_SHIFT)
@@ -328,7 +328,7 @@
                                                      /* Bits 23-19 Reserved */
 #define LPI2C_MCFGR1_PINCFG_SHIFT            (24)
 #define LPI2C_MCFGR1_PINCFG_MASK             (7 << LPI2C_MCFGR1_PINCFG_SHIFT)  /* Pin Configuration Bit Mask */
-#define LPI2C_MCFGR1_PINCFG(n)               ((n << LPI2C_MCFGR1_PINCFG_SHIFT) & LPI2C_MCFGR1_PINCFG_MASK)
+#define LPI2C_MCFGR1_PINCFG(n)               (((n) << LPI2C_MCFGR1_PINCFG_SHIFT) & LPI2C_MCFGR1_PINCFG_MASK)
 #  define LPI2C_MCFGR1_PINCFG0               (0 << LPI2C_MCFGR1_PINCFG_SHIFT)
 #  define LPI2C_MCFGR1_PINCFG1               (1 << LPI2C_MCFGR1_PINCFG_SHIFT)
 #  define LPI2C_MCFGR1_PINCFG2               (2 << LPI2C_MCFGR1_PINCFG_SHIFT)
@@ -343,17 +343,17 @@
 
 #define LPI2C_MCFG2_BUSIDLE_MASK            (0xfff << 0)  /* Bus Idle Timeout Period in Clock Cycles */
 #define LPI2C_MCFG2_BUSIDLE_DISABLE         (0)
-#define LPI2C_MCFG2_BUSIDLE(n)              (n & LPI2C_MCFG2_BUSIDLE_MASK)
+#define LPI2C_MCFG2_BUSIDLE(n)              ((n) & LPI2C_MCFG2_BUSIDLE_MASK)
                                                      /* Bits 15-12 Reserved */
 #define LPI2C_MCFG2_FILTSCL_SHIFT           (16)
 #define LPI2C_MCFG2_FILTSCL_MASK            (15 << LPI2C_MCFG2_FILTSCL_SHIFT)  /* Glitch Filter SCL */
 #define LPI2C_MCFG2_FILTSCL_DISABLE         (0 << LPI2C_MCFG2_FILTSCL_SHIFT)
-#define LPI2C_MCFG2_FILTSCL_CYCLES(n)       ((n << LPI2C_MCFG2_FILTSCL_SHIFT) & LPI2C_MCFG2_FILTSCL_MASK)
+#define LPI2C_MCFG2_FILTSCL_CYCLES(n)       (((n) << LPI2C_MCFG2_FILTSCL_SHIFT) & LPI2C_MCFG2_FILTSCL_MASK)
                                                      /* Bits 23-20 Reserved */
 #define LPI2C_MCFG2_FILTSDA_SHIFT           (24)
 #define LPI2C_MCFG2_FILTSDA_MASK            (15 << LPI2C_MCFG2_FILTSDA_SHIFT)  /* Glitch Filter SDA */
 #define LPI2C_MCFG2_FILTSDA_DISABLE         (0 << LPI2C_MCFG2_FILTSDA_SHIFT)
-#define LPI2C_MCFG2_FILTSDA_CYCLES(n)       ((n << LPI2C_MCFG2_FILTSDA_SHIFT) & LPI2C_MCFG2_FILTSDA_MASK)
+#define LPI2C_MCFG2_FILTSDA_CYCLES(n)       (((n) << LPI2C_MCFG2_FILTSDA_SHIFT) & LPI2C_MCFG2_FILTSDA_MASK)
                                                      /* Bits 31-28 Reserved */
 
 /* LPI2C Master Config Register 3  */
@@ -361,57 +361,57 @@
                                                      /* Bits 7-0 Reserved */
 #define LPI2C_MCFG3_PINLOW_SHIFT            (8)
 #define LPI2C_MCFG3_PINLOW_MASK             (0xfff << LPI2C_MCFG3_PINLOW_SHIFT)  /* Configure The Pin Low Timeout in Clock Cycles */
-#define LPI2C_MCFG3_PINLOW_CYCLES(n)        ((n << LPI2C_MCFG3_PINLOW_SHIFT) & LPI2C_MCFG3_PINLOW_MASK)
+#define LPI2C_MCFG3_PINLOW_CYCLES(n)        (((n) << LPI2C_MCFG3_PINLOW_SHIFT) & LPI2C_MCFG3_PINLOW_MASK)
                                                      /* Bits 31-20 Reserved */
 
 /* LPI2C Master Data Match Register  */
 
 #define LPI2C_MDMR_MATCH0_SHIFT             (0)
 #define LPI2C_MDMR_MATCH0_MASK              (0xff << LPI2C_MDMR_MATCH0_SHIFT)  /* Match 0 Value */
-#define LPI2C_MDMR_MATCH0(n)                ((n << LPI2C_MDMR_MATCH0_SHIFT) & LPI2C_MDMR_MATCH0_MASK)
+#define LPI2C_MDMR_MATCH0(n)                (((n) << LPI2C_MDMR_MATCH0_SHIFT) & LPI2C_MDMR_MATCH0_MASK)
                                                      /* Bits 15-8 Reserved */
 #define LPI2C_MDMR_MATCH1_SHIFT             (16)
 #define LPI2C_MDMR_MATCH1_MASK              (0xff << LPI2C_MDMR_MATCH1_SHIFT)  /* Match 1 Value */
-#define LPI2C_MDMR_MATCH1(n)                ((n << LPI2C_MDMR_MATCH1_SHIFT) & LPI2C_MDMR_MATCH1_MASK)
+#define LPI2C_MDMR_MATCH1(n)                (((n) << LPI2C_MDMR_MATCH1_SHIFT) & LPI2C_MDMR_MATCH1_MASK)
                                                      /* Bits 31-24 Reserved */
 
 /* LPI2C Master Clock Configuration Register 0 */
 
 #define LPI2C_MCCR0_CLKLO_SHIFT             (0)
 #define LPI2C_MCCR0_CLKLO_MASK              (0x3f << LPI2C_MCCR0_CLKLO_SHIFT)  /* Clock Low Period */
-#define LPI2C_MCCR0_CLKLO(n)                ((n << LPI2C_MCCR0_CLKLO_SHIFT) & LPI2C_MCCR0_CLKLO_MASK)
+#define LPI2C_MCCR0_CLKLO(n)                (((n) << LPI2C_MCCR0_CLKLO_SHIFT) & LPI2C_MCCR0_CLKLO_MASK)
                                                      /* Bits 7-6 Reserved */
 #define LPI2C_MCCR0_CLKHI_SHIFT             (8)
 #define LPI2C_MCCR0_CLKHI_MASK              (0x3f << LPI2C_MCCR0_CLKHI_SHIFT)  /* Clock High Period */
-#define LPI2C_MCCR0_CLKHI(n)                ((n << LPI2C_MCCR0_CLKHI_SHIFT) & LPI2C_MCCR0_CLKHI_MASK)
+#define LPI2C_MCCR0_CLKHI(n)                (((n) << LPI2C_MCCR0_CLKHI_SHIFT) & LPI2C_MCCR0_CLKHI_MASK)
                                                      /* Bits 15-14 Reserved */
 #define LPI2C_MCCR0_SETHOLD_SHIFT           (16)
 #define LPI2C_MCCR0_SETHOLD_MASK            (0x3f << LPI2C_MCCR0_SETHOLD_SHIFT)  /* Setup Hold Delay */
-#define LPI2C_MCCR0_SETHOLD(n)              ((n << LPI2C_MCCR0_SETHOLD_SHIFT) & LPI2C_MCCR0_SETHOLD_MASK)
+#define LPI2C_MCCR0_SETHOLD(n)              (((n) << LPI2C_MCCR0_SETHOLD_SHIFT) & LPI2C_MCCR0_SETHOLD_MASK)
                                                      /* Bits 23-22 Reserved */
 #define LPI2C_MCCR0_DATAVD_SHIFT            (24)
 #define LPI2C_MCCR0_DATAVD_MASK             (0x3f << LPI2C_MCCR0_DATAVD_SHIFT)  /* Setup Hold Delay */
-#define LPI2C_MCCR0_DATAVD(n)               ((n << LPI2C_MCCR0_DATAVD_SHIFT) & LPI2C_MCCR0_DATAVD_MASK)
+#define LPI2C_MCCR0_DATAVD(n)               (((n) << LPI2C_MCCR0_DATAVD_SHIFT) & LPI2C_MCCR0_DATAVD_MASK)
                                                      /* Bits 31-30 Reserved */
 
 /* LPI2C Master Clock Configuration Register 1 */
 
 #define LPI2C_MCCR1_CLKLO_SHIFT             (0)
 #define LPI2C_MCCR1_CLKLO_MASK              (0x3f << LPI2C_MCCR1_CLKLO_SHIFT)  /* Clock Low Period */
-#define LPI2C_MCCR1_CLKLO(n)                ((n << LPI2C_MCCR1_CLKLO_SHIFT) & LPI2C_MCCR1_CLKLO_MASK)
+#define LPI2C_MCCR1_CLKLO(n)                (((n) << LPI2C_MCCR1_CLKLO_SHIFT) & LPI2C_MCCR1_CLKLO_MASK)
                                                      /* Bits 7-6 Reserved */
 #define LPI2C_MCCR1_CLKHI_SHIFT             (8)
 #define LPI2C_MCCR1_CLKHI_MASK              (0x3f << LPI2C_MCCR1_CLKHI_SHIFT)  /* Clock High Period */
-#define LPI2C_MCCR1_CLKHI(n)                ((n << LPI2C_MCCR1_CLKHI_SHIFT) & LPI2C_MCCR1_CLKHI_MASK)
+#define LPI2C_MCCR1_CLKHI(n)                (((n) << LPI2C_MCCR1_CLKHI_SHIFT) & LPI2C_MCCR1_CLKHI_MASK)
                                                      /* Bits 15-14 Reserved */
 #define LPI2C_MCCR1_SETHOLD_SHIFT           (16)
 #define LPI2C_MCCR1_SETHOLD_MASK            (0x3f << LPI2C_MCCR1_SETHOLD_SHIFT)  /* Setup Hold Delay */
-#define LPI2C_MCCR1_SETHOLD(n)              ((n << LPI2C_MCCR1_SETHOLD_SHIFT) & LPI2C_MCCR1_SETHOLD_MASK)
+#define LPI2C_MCCR1_SETHOLD(n)              (((n) << LPI2C_MCCR1_SETHOLD_SHIFT) & LPI2C_MCCR1_SETHOLD_MASK)
 
                                                      /* Bits 23-22 Reserved */
 #define LPI2C_MCCR1_DATAVD_SHIFT            (24)
 #define LPI2C_MCCR1_DATAVD_MASK             (0x3f << LPI2C_MCCR1_DATAVD_SHIFT)  /* Setup Hold Delay */
-#define LPI2C_MCCR1_DATAVD(n)               ((n << LPI2C_MCCR1_DATAVD_SHIFT) & LPI2C_MCCR1_DATAVD_MASK)
+#define LPI2C_MCCR1_DATAVD(n)               (((n) << LPI2C_MCCR1_DATAVD_SHIFT) & LPI2C_MCCR1_DATAVD_MASK)
 
                                                      /* Bits 31-30 Reserved */
 
@@ -420,13 +420,13 @@
 #define LPI2C_MFCR_TXWATER_SHIFT            (0)
 #define LPI2C_MFCR_TXWATER_MASK             (3 << LPI2C_MFCR_TXWATER_SHIFT)  /* Transmit FIFO Watermark*/
 
-#define LPI2C_MFCR_TXWATER(n)               ((n << LPI2C_MFCR_TXWATER_SHIFT) &  LPI2C_MFCR_TXWATER_MASK)  /* Transmit FIFO Watermark */
+#define LPI2C_MFCR_TXWATER(n)               (((n) << LPI2C_MFCR_TXWATER_SHIFT) &  LPI2C_MFCR_TXWATER_MASK)  /* Transmit FIFO Watermark */
 
                                                      /* Bits 15-2 Reserved */
 #define LPI2C_MFCR_RXWATER_SHIFT            (16)
 #define LPI2C_MFCR_RXWATER_MASK             (3 << LPI2C_MFCR_RXWATER_SHIFT)  /* Receive FIFO Watermark */
 
-#define LPI2C_MFCR_RXWATER(n)               ((n << LPI2C_MFCR_RXWATER_SHIFT) &  LPI2C_MFCR_RXWATER_MASK)  /* Transmit FIFO Watermark */
+#define LPI2C_MFCR_RXWATER(n)               (((n) << LPI2C_MFCR_RXWATER_SHIFT) &  LPI2C_MFCR_RXWATER_MASK)  /* Transmit FIFO Watermark */
 
                                                      /* Bits 31-18 Reserved */
 
@@ -445,10 +445,10 @@
 
 #define LPI2C_MTDR_DATA_SHIFT               (0)
 #define LPI2C_MTDR_DATA_MASK                (0xff << LPI2C_MTDR_DATA_SHIFT)  /* Transmit Data */
-#define LPI2C_MTDR_DATA(n)                  (n & LPI2C_MTDR_DATA_MASK)
+#define LPI2C_MTDR_DATA(n)                  ((n) & LPI2C_MTDR_DATA_MASK)
 #define LPI2C_MTDR_CMD_SHIFT                (8)
 #define LPI2C_MTDR_CMD_MASK                 (7 << LPI2C_MTDR_CMD_SHIFT)  /* Command Data */
-#define LPI2C_MTDR_CMD(n)                   ((n << LPI2C_MTDR_CMD_SHIFT) & LPI2C_MTDR_CMD_MASK)
+#define LPI2C_MTDR_CMD(n)                   (((n) << LPI2C_MTDR_CMD_SHIFT) & LPI2C_MTDR_CMD_MASK)
 #  define LPI2C_MTDR_CMD_TXD                (0 << LPI2C_MTDR_CMD_SHIFT)
 #  define LPI2C_MTDR_CMD_RXD                (1 << LPI2C_MTDR_CMD_SHIFT)
 #  define LPI2C_MTDR_CMD_STOP               (2 << LPI2C_MTDR_CMD_SHIFT)
@@ -543,7 +543,7 @@
                                                       /* Bits 15-14 Reserved */
 #define LPI2C_SCFG1_ADDRCFG_SHIFT           (16)
 #define LPI2C_SCFG1_ADDRCFG_MASK            (7 << LPI2C_SCFG1_ADDRCFG_SHIFT)  /* Address Configuration Bit Mask */
-#define LPI2C_SCFG1_ADDRCFG(n)              ((n << LPI2C_SCFG1_ADDRCFG_SHIFT) & LPI2C_SCFG1_ADDRCFG_MASK)
+#define LPI2C_SCFG1_ADDRCFG(n)              (((n) << LPI2C_SCFG1_ADDRCFG_SHIFT) & LPI2C_SCFG1_ADDRCFG_MASK)
 #  define LPI2C_SCFG1_ADDRCFG0              (0 << LPI2C_SCFG1_ADDRCFG_SHIFT)
 #  define LPI2C_SCFG1_ADDRCFG1              (2 << LPI2C_SCFG1_ADDRCFG_SHIFT)
 #  define LPI2C_SCFG1_ADDRCFG2              (2 << LPI2C_SCFG1_ADDRCFG_SHIFT)
@@ -557,21 +557,21 @@
 /* LPI2C Slave Configuration Register 2  */
 
 #define LPI2C_SCFG2_CLKHOLD_MASK            (15 << 0) /* Clock Hold Time */
-#define LPI2C_SCFG2_CLKHOLD(n)              (n & LPI2C_SCFG2_CLKHOLD_MASK)
+#define LPI2C_SCFG2_CLKHOLD(n)              ((n) & LPI2C_SCFG2_CLKHOLD_MASK)
                                                       /* Bits 7-4 Reserved */
 #define LPI2C_SCFG2_DATAVD_SHIFT            (8)
 #define LPI2C_SCFG2_DATAVD_MASK             (0x3f << LPI2C_SCFG2_DATAVD_SHIFT)  /* Data Valid Delay */
-#define LPI2C_SCFG2_DATAVD(n)               ((n << LPI2C_SCFG2_DATAVD_SHIFT) & LPI2C_SCFG2_DATAVD_MASK)
+#define LPI2C_SCFG2_DATAVD(n)               (((n) << LPI2C_SCFG2_DATAVD_SHIFT) & LPI2C_SCFG2_DATAVD_MASK)
                                                       /* Bits 15-14 Reserved */
 #define LPI2C_SCFG2_FILTSCL_SHIFT           (16)
 #define LPI2C_SCFG2_FILTSCL_MASK            (15 << LPI2C_SCFG2_FILTSCL_SHIFT)  /* Glitch Filter SCL */
 #define LPI2C_SCFG2_FILTSCL_DISABLE         (0 << LPI2C_SCFG2_FILTSCL_SHIFT)
-#define LPI2C_SCFG2_FILTSCL_CYCLES(n)       ((n << LPI2C_SCFG2_FILTSCL_SHIFT) & LPI2C_SCFG2_FILTSCL_MASK)
+#define LPI2C_SCFG2_FILTSCL_CYCLES(n)       (((n) << LPI2C_SCFG2_FILTSCL_SHIFT) & LPI2C_SCFG2_FILTSCL_MASK)
                                                       /* Bits 23-20 Reserved */
 #define LPI2C_SCFG2_FILTSDA_SHIFT           (24)
 #define LPI2C_SCFG2_FILTSDA_MASK            (15 << LPI2C_SCFG2_FILTSDA_SHIFT)  /* Glitch Filter SDA */
 #define LPI2C_SCFG2_FILTSDA_DISABLE         (0 << LPI2C_SCFG2_FILTSDA_SHIFT)
-#define LPI2C_SCFG2_FILTSDA_CYCLES(n)       ((n << LPI2C_SCFG2_FILTSDA_SHIFT) & LPI2C_SCFG2_FILTSDA_MASK)
+#define LPI2C_SCFG2_FILTSDA_CYCLES(n)       (((n) << LPI2C_SCFG2_FILTSDA_SHIFT) & LPI2C_SCFG2_FILTSDA_MASK)
                                                       /* Bits 31-28 Reserved */
 
 /* LPI2C Slave Address Match Register  */
@@ -579,11 +579,11 @@
                                                       /* Bit 0 Reserved */
 #define LPI2C_SAMR_ADDR0_SHIFT              (1)
 #define LPI2C_SAMR_ADDR0_MASK               (0x3ff << LPI2C_SAMR_ADDR0_SHIFT)  /* Address 0 Value */
-#define LPI2C_SAMR_ADDR0(n)                 ((n << LPI2C_SAMR_ADDR0_SHIFT) & LPI2C_SAMR_ADDR0_MASK)
+#define LPI2C_SAMR_ADDR0(n)                 (((n) << LPI2C_SAMR_ADDR0_SHIFT) & LPI2C_SAMR_ADDR0_MASK)
                                                       /* Bits 16-11 Reserved */
 #define LPI2C_SAMR_ADDR1_SHIFT              (17)
 #define LPI2C_SAMR_ADDR1_MASK               (0x3ff << LPI2C_SAMR_ADDR1_SHIFT)  /* Address 1 Value */
-#define LPI2C_SAMR_ADDR1(n)                 ((n << LPI2C_SAMR_ADDR1_SHIFT) & LPI2C_SAMR_ADDR1_MASK)
+#define LPI2C_SAMR_ADDR1(n)                 (((n) << LPI2C_SAMR_ADDR1_SHIFT) & LPI2C_SAMR_ADDR1_MASK)
                                                       /* Bits 31-27 Reserved */
 
 /* LPI2C Slave Address Status Register  */
@@ -606,14 +606,14 @@
 
 #define LPI2C_STDR_DATA_SHIFT               (0)
 #define LPI2C_STDR_DATA_MASK                (0xff << LPI2C_STDR_DATA_SHIFT)  /* Transmit Data */
-#define LPI2C_STDR_DATA(n)                  ((n << LPI2C_STDR_DATA_SHIFT) & LPI2C_STDR_DATA_MASK)
+#define LPI2C_STDR_DATA(n)                  (((n) << LPI2C_STDR_DATA_SHIFT) & LPI2C_STDR_DATA_MASK)
                                                       /* Bits 31-8 Reserved */
 
 /* LPI2C Slave Receive Data Register  */
 
 #define LPI2C_SRDR_DATA_SHIFT               (0)
 #define LPI2C_SRDR_DATA_MASK                (0xff << LPI2C_SRDR_DATA_SHIFT)  /* Receive Data */
-#define LPI2C_SRDR_DATA(n)                  ((n << LPI2C_SRDR_DATA_SHIFT) & LPI2C_SRDR_DATA_MASK)
+#define LPI2C_SRDR_DATA(n)                  (((n) << LPI2C_SRDR_DATA_SHIFT) & LPI2C_SRDR_DATA_MASK)
                                                       /* Bits 13-8 Reserved */
 #define LPI2C_STAR_SOF                      (1 << 14) /* RX Empty */
 #define LPI2C_STAR_RXEMPTY                  (1 << 15) /* Start Of Frame */