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 2021/06/16 17:23:28 UTC

[incubator-nuttx] branch master updated: risc-v/mpfs: add dma support

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


The following commit(s) were added to refs/heads/master by this push:
     new 673f951  risc-v/mpfs: add dma support
673f951 is described below

commit 673f9519eb84a3a6ec2c5a16424e1b5d383ac216
Author: Janne Rosberg <ja...@offcode.fi>
AuthorDate: Fri May 28 18:27:01 2021 +0300

    risc-v/mpfs: add dma support
---
 arch/risc-v/src/mpfs/Kconfig                   |  10 +-
 arch/risc-v/src/mpfs/Make.defs                 |   4 +
 arch/risc-v/src/mpfs/hardware/mpfs_dma.h       | 136 +++++++
 arch/risc-v/src/mpfs/hardware/mpfs_memorymap.h |   3 +-
 arch/risc-v/src/mpfs/mpfs_dma.c                | 516 +++++++++++++++++++++++++
 arch/risc-v/src/mpfs/mpfs_dma.h                |  93 +++++
 6 files changed, 760 insertions(+), 2 deletions(-)

diff --git a/arch/risc-v/src/mpfs/Kconfig b/arch/risc-v/src/mpfs/Kconfig
index 44bb9f3..dc8ced7 100755
--- a/arch/risc-v/src/mpfs/Kconfig
+++ b/arch/risc-v/src/mpfs/Kconfig
@@ -105,7 +105,15 @@ config MPFS_I2C1
 
 endmenu
 
-menu "MPFS Others"
+config MPFS_DMA
+	bool "MPFS DMA (PDMA)"
+	default n
+	select ARCH_DMA
+	---help---
+		Enable DMA Support. MPFS DMA is Memory-to-Memory only.
 
+menu "MPFS Others"
 
 endmenu
+
+
diff --git a/arch/risc-v/src/mpfs/Make.defs b/arch/risc-v/src/mpfs/Make.defs
index 5582815..35bbc00 100755
--- a/arch/risc-v/src/mpfs/Make.defs
+++ b/arch/risc-v/src/mpfs/Make.defs
@@ -54,6 +54,10 @@ CHIP_CSRCS += mpfs_lowputc.c mpfs_serial.c
 CHIP_CSRCS += mpfs_start.c mpfs_timerisr.c
 CHIP_CSRCS += mpfs_gpio.c mpfs_systemreset.c
 
+ifeq ($(CONFIG_MPFS_DMA),y)
+CHIP_CSRCS  += mpfs_dma.c
+endif
+
 ifeq ($(CONFIG_BUILD_PROTECTED),y)
 CMN_CSRCS  += riscv_task_start.c riscv_pthread_start.c
 CMN_CSRCS  += riscv_signal_dispatch.c riscv_pmp.c
diff --git a/arch/risc-v/src/mpfs/hardware/mpfs_dma.h b/arch/risc-v/src/mpfs/hardware/mpfs_dma.h
new file mode 100755
index 0000000..4226529
--- /dev/null
+++ b/arch/risc-v/src/mpfs/hardware/mpfs_dma.h
@@ -0,0 +1,136 @@
+/****************************************************************************
+ * arch/risc-v/src/mpfs/hardware/mpfs_dma.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_RISCV_SRC_MPFS_HARDWARE_MPFS_DMA_H
+#define __ARCH_RISCV_SRC_MPFS_HARDWARE_MPFS_DMA_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include "hardware/mpfs_memorymap.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Register offsets *********************************************************/
+
+#define MPFS_DMA_CONTROL_OFFSET          0x0000 /* Channel control register */
+#define MPFS_DMA_NEXT_CONFIG_OFFSET      0x0004 /* Next transfer type */
+#define MPFS_DMA_NEXT_BYTES_OFFSET       0x0008 /* Number of bytes to move */
+#define MPFS_DMA_NEXT_DESTINATION_OFFSET 0x0010 /* Destination start address */
+#define MPFS_DMA_NEXT_SOURCE_OFFSET      0x0018 /* Source start address */
+#define MPFS_DMA_EXEC_CONFIG_OFFSET      0x0104 /* Active transfer type */
+#define MPFS_DMA_EXEC_BYTES_OFFSET       0x0108 /* Number of bytes remaining */
+#define MPFS_DMA_EXEC_DESTINATION_OFFSET 0x0110 /* Destination current address */
+#define MPFS_DMA_EXEC_SOURCE_OFFSET      0x0118 /* Source current address */
+
+#define MPFS_DMA_CHANNEL_OFFSET          0x1000 /* Offset to channels */
+
+#define MPFS_DMA_REG_OFFSET(x) \
+          (uint64_t)(MPFS_PDMA_BASE + (MPFS_DMA_CHANNEL_OFFSET * (x)))
+
+/* Register bit field definitions *******************************************/
+
+/* Control register */
+
+/* Indicates that the channel is in use. Setting this bit clears all of the
+ * channel’s Next registers (NextConfig, NextBytes, NextDestination, and
+ * NextSource). This bit can only be cleared when run (CR bit 0) is low.
+ */
+
+#define DMA_CONTROL_CLAIM_SHIFT      (0) /* Bit: 0: claim */
+#define DMA_CONTROL_CLAIM_MASK       (1 << DMA_CONTROL_CLAIM_SHIFT)
+#  define DMA_CONTROL_CLAIM          (0 << DMA_CONTROL_CLAIM_SHIFT)
+
+/* Setting this bit starts a DMA transfer by copying the Next registers
+ * into their Exec counterparts.
+ */
+
+#define DMA_CONTROL_RUN_SHIFT        (1) /* Bit: 1: run */
+#define DMA_CONTROL_RUN_MASK         (1 << DMA_CONTROL_RUN_SHIFT)
+#  define DMA_CONTROL_RUN            (1 << DMA_CONTROL_RUN_SHIFT)
+
+/* Setting this bit will trigger the channel’s Done interrupt once
+ * a transfer is complete.
+ */
+
+#define DMA_CONTROL_DONEIE_SHIFT     (14) /* Bit: 14: Done Irq enable */
+#define DMA_CONTROL_DONEIE_MASK      (1 << DMA_CONTROL_DONEIE_SHIFT)
+#  define DMA_CONTROL_DONEIE         (1 << DMA_CONTROL_DONEIE_SHIFT)
+
+/* Setting this bit will trigger the channel’s Done interrupt once
+ * a transfer is complete.
+ */
+
+#define DMA_CONTROL_ERRORIE_SHIFT    (15) /* Bit: 15: Error Irq enable */
+#define DMA_CONTROL_ERRORIE_MASK     (1 << DMA_CONTROL_ERRORIE_SHIFT)
+#  define DMA_CONTROL_ERRORIE        (1 << DMA_CONTROL_ERRORIE_SHIFT)
+
+/* Indicates that a transfer has completed since the channel was claimed */
+
+#define DMA_CONTROL_DONE_SHIFT       (30) /* Bit: 30: Done */
+#define DMA_CONTROL_DONE_MASK        (1 << DMA_CONTROL_DONE_SHIFT)
+#  define DMA_CONTROL_DONE           (1 << DMA_CONTROL_DONE_SHIFT)
+
+/* Indicates that a transfer error has occurred since the channel
+ * was claimed
+ */
+
+#define DMA_CONTROL_ERROR_SHIFT      (31) /* Bit: 31: Error */
+#define DMA_CONTROL_ERROR_MASK       (1 << DMA_CONTROL_ERROR_SHIFT)
+#  define DMA_CONTROL_ERROR          (1 << DMA_CONTROL_ERROR_SHIFT)
+
+/* Channel Next Configuration Register */
+
+/* If set, the Exec registers are reloaded from the Next registers once a
+ * transfer is complete. The repeat bit must be cleared by software
+ * for the sequence to stop
+ */
+
+#define DMA_NEXT_CONFIG_REPEAT_SHIFT (2) /* Bit: 2: repeat */
+#define DMA_NEXT_CONFIG_REPEAT_MASK  (1 << DMA_NEXT_CONFIG_REPEAT_SHIFT)
+#  define DMA_NEXT_CONFIG_REPEAT     (1 << DMA_NEXT_CONFIG_REPEAT_SHIFT)
+
+/* Enforces strict ordering by only allowing one of each transfer type
+ * in-flight at a time
+ */
+
+#define DMA_NEXT_CONFIG_ORDER_SHIFT  (3) /* Bit: 3: order */
+#define DMA_NEXT_CONFIG_ORDER_MASK   (1 << DMA_NEXT_CONFIG_ORDER_SHIFT)
+#  define DMA_NEXT_CONFIG_ORDER      (1 << DMA_NEXT_CONFIG_ORDER_SHIFT)
+
+/* WSIZE and RSIZE. Base 2 Logarithm of DMA transaction sizes.
+ * Example: 0 is 1 byte, 3 is 8 bytes, 5 is 32 bytes
+ * These fields are WARL (Write-Any Read-Legal), so the actual size used
+ * can be determined by reading the field after writing the requested size.
+ * */
+
+#define DMA_NEXT_CONFIG_WSIZE_SHIFT  (24) /* Bits: 24-27: write size */
+#define DMA_NEXT_CONFIG_WSIZE_MASK   (15 << DMA_NEXT_CONFIG_WSIZE_SHIFT)
+#  define DMA_NEXT_CONFIG_WSIZE(x)   (x << DMA_NEXT_CONFIG_WSIZE_SHIFT)
+
+#define DMA_NEXT_CONFIG_RSIZE_SHIFT  (28) /* Bits: 28-31: read size */
+#define DMA_NEXT_CONFIG_RSIZE_MASK   (15 << DMA_NEXT_CONFIG_RSIZE_SHIFT)
+#  define DMA_NEXT_CONFIG_RSIZE(x)   (x << DMA_NEXT_CONFIG_RSIZE_SHIFT)
+
+#endif /* __ARCH_RISCV_SRC_MPFS_HARDWARE_MPFS_DMA_H */
diff --git a/arch/risc-v/src/mpfs/hardware/mpfs_memorymap.h b/arch/risc-v/src/mpfs/hardware/mpfs_memorymap.h
index 4d07554..ff7c0e6 100755
--- a/arch/risc-v/src/mpfs/hardware/mpfs_memorymap.h
+++ b/arch/risc-v/src/mpfs/hardware/mpfs_memorymap.h
@@ -27,8 +27,9 @@
 
 /* Register Base Address ****************************************************/
 
-#define MPFS_PLIC_BASE                 (0x0C000000UL)
 #define MPFS_CLINT_BASE                (0x02000000UL)
+#define MPFS_PDMA_BASE                 (0x03000000UL)
+#define MPFS_PLIC_BASE                 (0x0C000000UL)
 
 #define MPFS_UART0_LO_BASE             (0x20000000UL)
 #define MPFS_WDOG0_LO_BASE             (0x20001000UL)
diff --git a/arch/risc-v/src/mpfs/mpfs_dma.c b/arch/risc-v/src/mpfs/mpfs_dma.c
new file mode 100755
index 0000000..d2454c5
--- /dev/null
+++ b/arch/risc-v/src/mpfs/mpfs_dma.c
@@ -0,0 +1,516 @@
+/****************************************************************************
+ * arch/risc-v/src/mpfs/mpfs_dma.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+#include <assert.h>
+#include <debug.h>
+
+#include <nuttx/arch.h>
+#include <arch/board/board.h>
+
+#include "riscv_arch.h"
+#include "hardware/mpfs_dma.h"
+#include "mpfs_dma.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define DMA_MAX_TRANSACTION_SIZE (0x0f)
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static uint8_t g_channel_nextcfg_wsize[MPFS_DMA_NUM_CHANNELS] =
+{
+  DMA_MAX_TRANSACTION_SIZE, DMA_MAX_TRANSACTION_SIZE,
+  DMA_MAX_TRANSACTION_SIZE, DMA_MAX_TRANSACTION_SIZE
+};
+
+static uint8_t g_channel_nextcfg_rsize[MPFS_DMA_NUM_CHANNELS] =
+{
+  DMA_MAX_TRANSACTION_SIZE, DMA_MAX_TRANSACTION_SIZE,
+  DMA_MAX_TRANSACTION_SIZE, DMA_MAX_TRANSACTION_SIZE
+};
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: mpfs_dma_setup_transfer
+ *
+ * Description:
+ *   Set DMA transfer config for channel.
+ *
+ * Parameters:
+ *   channel   - Channel number 0-3
+ *   config    - Pointer to the config structure.
+ *
+ * Returned Value:
+ *   Zero (OK) is returned on success. A negated errno value is returned on
+ *   failure.
+ *
+ ****************************************************************************/
+
+int mpfs_dma_setup_transfer(unsigned int channel,
+                            struct mpfs_dma_channel_config *config)
+{
+  if (channel >= MPFS_DMA_NUM_CHANNELS)
+    {
+      dmawarn("Illegal channel");
+      return -EINVAL;
+    }
+
+  if (config->src_addr == 0)
+    {
+      dmawarn("Illegal source address\n");
+      return -EINVAL;
+    }
+
+  if (config->dest_addr == 0)
+    {
+      dmawarn("Illegal destination address\n");
+      return -EINVAL;
+    }
+
+  /* If transaction is in progress, return error. */
+
+  if (getreg32(MPFS_DMA_REG_OFFSET(channel)) & DMA_CONTROL_RUN_MASK)
+    {
+      dmawarn("channel busy\n");
+      return -EBUSY;
+    }
+
+  /* Set or clear the interrupts for the transfer. */
+
+  if (config->enable_done_int)
+    {
+      dmainfo("enable done irq\n");
+      modifyreg32(MPFS_DMA_REG_OFFSET(channel) + MPFS_DMA_CONTROL_OFFSET,
+                  0, DMA_CONTROL_DONEIE);
+    }
+  else
+    {
+      dmainfo("disable done irq\n");
+      modifyreg32(MPFS_DMA_REG_OFFSET(channel) + MPFS_DMA_CONTROL_OFFSET,
+                  DMA_CONTROL_DONEIE_MASK, 0);
+    }
+
+  if (config->enable_err_int)
+    {
+      dmainfo("enable err irq\n");
+      modifyreg32(MPFS_DMA_REG_OFFSET(channel) + MPFS_DMA_CONTROL_OFFSET,
+                  0, DMA_CONTROL_ERRORIE);
+    }
+  else
+    {
+      dmainfo("disable err irq\n");
+      modifyreg32(MPFS_DMA_REG_OFFSET(channel) + MPFS_DMA_CONTROL_OFFSET,
+                  DMA_CONTROL_ERRORIE_MASK, 0);
+    }
+
+  /* clear Next registers. */
+
+  modifyreg32(MPFS_DMA_REG_OFFSET(channel) + MPFS_DMA_CONTROL_OFFSET,
+              0, DMA_CONTROL_CLAIM);
+
+  /* clear Done and Error */
+
+  modifyreg32(MPFS_DMA_REG_OFFSET(channel) + MPFS_DMA_CONTROL_OFFSET,
+              DMA_CONTROL_DONE_MASK | DMA_CONTROL_ERROR_MASK, 0);
+
+  /* Setup the source and destination addresses. */
+
+  putreg64(config->dest_addr,
+           MPFS_DMA_REG_OFFSET(channel) + MPFS_DMA_NEXT_DESTINATION_OFFSET);
+  putreg64(config->src_addr,
+           MPFS_DMA_REG_OFFSET(channel) + MPFS_DMA_NEXT_SOURCE_OFFSET);
+
+  /* Set the transfer size. */
+
+  putreg64(config->num_bytes,
+           MPFS_DMA_REG_OFFSET(channel) + MPFS_DMA_NEXT_BYTES_OFFSET);
+
+  /* Setup repeat and force order requirements. */
+
+  if (config->repeat)
+    {
+      modifyreg32(MPFS_DMA_REG_OFFSET(channel) + MPFS_DMA_NEXT_CONFIG_OFFSET,
+                  0, DMA_NEXT_CONFIG_REPEAT);
+    }
+  else
+    {
+      modifyreg32(MPFS_DMA_REG_OFFSET(channel) + MPFS_DMA_NEXT_CONFIG_OFFSET,
+                  DMA_NEXT_CONFIG_REPEAT_MASK, 0);
+    }
+
+  if (config->force_order)
+    {
+      modifyreg32(MPFS_DMA_REG_OFFSET(channel) + MPFS_DMA_NEXT_CONFIG_OFFSET,
+                  0, DMA_NEXT_CONFIG_ORDER);
+    }
+  else
+    {
+      modifyreg32(MPFS_DMA_REG_OFFSET(channel) + MPFS_DMA_NEXT_CONFIG_OFFSET,
+                  DMA_NEXT_CONFIG_ORDER_MASK, 0);
+    }
+
+  /* Set PDMA transaction size to maximum. */
+
+  modifyreg32(MPFS_DMA_REG_OFFSET(channel) + MPFS_DMA_NEXT_CONFIG_OFFSET,
+              DMA_NEXT_CONFIG_WSIZE_MASK,
+              DMA_NEXT_CONFIG_WSIZE(g_channel_nextcfg_wsize[channel]));
+
+  modifyreg32(MPFS_DMA_REG_OFFSET(channel) + MPFS_DMA_NEXT_CONFIG_OFFSET,
+              DMA_NEXT_CONFIG_RSIZE_MASK,
+              DMA_NEXT_CONFIG_RSIZE(g_channel_nextcfg_wsize[channel]));
+
+  dmainfodumpbuffer("dma regs", (uint8_t *)MPFS_DMA_REG_OFFSET(channel),
+                    MPFS_DMA_NEXT_SOURCE_OFFSET + 8);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: mpfs_dma_set_transaction_size
+ *
+ * Description:
+ *   Set read and write transaction size for mpfs_dma_setup_transfer()
+ *
+ * Parameters:
+ *   channel     - Channel number 0-3
+ *   write_size  - Write transaction size
+ *   read_size   - Read transaction size
+ *
+ * Returned Value:
+ *   Zero (OK) is returned on success. A negated errno value is returned on
+ *   failure.
+ *
+ ****************************************************************************/
+
+int mpfs_dma_set_transaction_size(unsigned int channel,
+                                  uint8_t write_size, uint8_t read_size)
+{
+  if (channel >= MPFS_DMA_NUM_CHANNELS)
+    {
+      dmawarn("Illegal channel\n");
+      return -EINVAL;
+    }
+
+  if (write_size > DMA_MAX_TRANSACTION_SIZE)
+    {
+      dmawarn("Illegal write size\n");
+      return -EINVAL;
+    }
+
+  if (read_size > DMA_MAX_TRANSACTION_SIZE)
+    {
+      dmawarn("Illegal write size\n");
+      return -EINVAL;
+    }
+
+  dmainfo("new default dma transaction size. channel:%d write:%d, read:%d\n",
+          channel, write_size, read_size);
+  g_channel_nextcfg_wsize[channel] = write_size;
+  g_channel_nextcfg_rsize[channel] = read_size;
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: mpfs_dma_start
+ *
+ * Description:
+ *   Start DMA transfer.
+ *
+ * Parameters:
+ *   channel     - Channel number 0-3
+ *
+ * Returned Value:
+ *   Zero (OK) is returned on success. A negated errno value is returned on
+ *   failure.
+ *
+ ****************************************************************************/
+
+int mpfs_dma_start(unsigned int channel)
+{
+  if (channel >= MPFS_DMA_NUM_CHANNELS)
+    {
+      dmawarn("Illegal channel\n");
+      return -EINVAL;
+    }
+
+  dmainfo("start dma channel:%d\n", channel);
+  modifyreg32(MPFS_DMA_REG_OFFSET(channel) + MPFS_DMA_CONTROL_OFFSET,
+              0, DMA_CONTROL_RUN);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: mpfs_dma_get_transfer_type
+ *
+ * Description:
+ *   Return channels active config.
+ *
+ * Parameters:
+ *   channel     - Channel number 0-3
+ *
+ * Returned Value:
+ *   0      - Illegal channel
+ *   bit 2  - Repeat
+ *   bit 3  - Strict ordering
+ *
+ ****************************************************************************/
+
+uint32_t mpfs_dma_get_transfer_type(unsigned int channel)
+{
+  if (channel >= MPFS_DMA_NUM_CHANNELS)
+    {
+      dmawarn("Illegal channel\n");
+      return 0;
+    }
+
+  return getreg32(MPFS_DMA_REG_OFFSET(channel) +
+                  MPFS_DMA_EXEC_CONFIG_OFFSET);
+}
+
+/****************************************************************************
+ * Name: mpfs_dma_get_bytes_remaining
+ *
+ * Description:
+ *   Return number of bytes remaining on transfer.
+ *
+ * Parameters:
+ *   channel     - Channel number 0-3
+ *
+ * Returned Value:
+ *   Number of bytes remaining
+ *
+ ****************************************************************************/
+
+uint64_t mpfs_dma_get_bytes_remaining(unsigned int channel)
+{
+  if (channel >= MPFS_DMA_NUM_CHANNELS)
+    {
+      dmawarn("Illegal channel\n");
+      return 0;
+    }
+
+  return getreg64(MPFS_DMA_REG_OFFSET(channel) + MPFS_DMA_EXEC_BYTES_OFFSET);
+}
+
+/****************************************************************************
+ * Name: mpfs_dma_get_current_dest
+ *
+ * Description:
+ *   Return current destination address of transfer
+ *
+ * Parameters:
+ *   channel     - Channel number 0-3
+ *
+ * Returned Value:
+ *   Current destination address
+ *
+ ****************************************************************************/
+
+uint64_t mpfs_dma_get_current_destination(unsigned int channel)
+{
+  if (channel >= MPFS_DMA_NUM_CHANNELS)
+    {
+      dmawarn("Illegal channel\n");
+      return 0;
+    }
+
+  return getreg64(MPFS_DMA_REG_OFFSET(channel) +
+                  MPFS_DMA_EXEC_DESTINATION_OFFSET);
+}
+
+/****************************************************************************
+ * Name: mpfs_dma_get_current_source
+ *
+ * Description:
+ *   Return current sourceaddress of transfer
+ *
+ * Parameters:
+ *   channel     - Channel number 0-3
+ *
+ * Returned Value:
+ *   Current source address
+ *
+ ****************************************************************************/
+
+uint64_t mpfs_dma_get_current_source(unsigned int channel)
+{
+  if (channel >= MPFS_DMA_NUM_CHANNELS)
+    {
+      dmawarn("Illegal channel\n");
+      return 0;
+    }
+
+  return getreg64(MPFS_DMA_REG_OFFSET(channel) +
+                  MPFS_DMA_EXEC_SOURCE_OFFSET);
+}
+
+/****************************************************************************
+ * Name: mpfs_dma_get_complete_status
+ *
+ * Description:
+ *   Return complete status for DMA channel
+ *
+ * Parameters:
+ *   channel     - Channel number 0-3
+ *
+ * Returned Value:
+ *   0  - Not completed
+ *   1  - Transfer completed
+ *
+ ****************************************************************************/
+
+int mpfs_dma_get_complete_status(unsigned int channel)
+{
+  uint32_t control;
+
+  if (channel >= MPFS_DMA_NUM_CHANNELS)
+    {
+      dmawarn("Illegal channel\n");
+      return 0;
+    }
+
+  control = getreg32(MPFS_DMA_REG_OFFSET(channel) +
+                       MPFS_DMA_CONTROL_OFFSET);
+
+  return ((control & DMA_CONTROL_DONE_MASK) >> DMA_CONTROL_DONE_SHIFT);
+}
+
+/****************************************************************************
+ * Name: mpfs_dma_get_error_status
+ *
+ * Description:
+ *   Return error status for DMA channel
+ *
+ * Parameters:
+ *   channel     - Channel number 0-3
+ *
+ * Returned Value:
+ *   0  - No Error
+ *   1  - Transfer Errror
+ *
+ ****************************************************************************/
+
+int mpfs_dma_get_error_status(unsigned int channel)
+{
+  uint32_t control;
+
+  if (channel >= MPFS_DMA_NUM_CHANNELS)
+    {
+      dmawarn("Illegal channel\n");
+      return 0;
+    }
+
+  control = getreg32(MPFS_DMA_REG_OFFSET(channel) +
+                       MPFS_DMA_CONTROL_OFFSET);
+
+  return ((control & DMA_CONTROL_ERROR_MASK) >> DMA_CONTROL_ERROR_SHIFT);
+}
+
+/****************************************************************************
+ * Name: mpfs_dma_clear_complete_status
+ *
+ * Description:
+ *   Clear and return complete status for DMA channel
+ *
+ * Parameters:
+ *   channel     - Channel number 0-3
+ *
+ * Returned Value:
+ *   0  - Not completed
+ *   1  - Transfer completed
+ *
+ ****************************************************************************/
+
+int mpfs_dma_clear_complete_status(unsigned int channel)
+{
+  int status = 0;
+  uint32_t control;
+
+  if (channel >= MPFS_DMA_NUM_CHANNELS)
+    {
+      dmawarn("Illegal channel\n");
+      return 0;
+    }
+
+  control = getreg32(MPFS_DMA_REG_OFFSET(channel) + MPFS_DMA_CONTROL_OFFSET);
+  if (control & DMA_CONTROL_DONE)
+    {
+      status = 1;
+    }
+
+  modifyreg32(MPFS_DMA_REG_OFFSET(channel) + MPFS_DMA_CONTROL_OFFSET,
+              DMA_CONTROL_DONE_MASK, 0);
+
+  return status;
+}
+
+/****************************************************************************
+ * Name: mpfs_dma_clear_error_status
+ *
+ * Description:
+ *   Clear and return error status for DMA channel
+ *
+ * Parameters:
+ *   channel     - Channel number 0-3
+ *
+ * Returned Value:
+ *   0  - No Error
+ *   1  - Transfer Errror
+ *
+ ****************************************************************************/
+
+int mpfs_dma_clear_error_status(unsigned int channel)
+{
+  int status = 0;
+  uint32_t control;
+
+  if (channel >= MPFS_DMA_NUM_CHANNELS)
+    {
+      dmawarn("Illegal channel\n");
+      return 0;
+    }
+
+  control = getreg32(MPFS_DMA_REG_OFFSET(channel) + MPFS_DMA_CONTROL_OFFSET);
+  if (control & DMA_CONTROL_ERROR)
+    {
+      status = 1;
+    }
+
+  modifyreg32(MPFS_DMA_REG_OFFSET(channel) + MPFS_DMA_CONTROL_OFFSET,
+              DMA_CONTROL_ERROR, 0);
+
+  return status;
+}
diff --git a/arch/risc-v/src/mpfs/mpfs_dma.h b/arch/risc-v/src/mpfs/mpfs_dma.h
new file mode 100755
index 0000000..7f401a7
--- /dev/null
+++ b/arch/risc-v/src/mpfs/mpfs_dma.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+ * arch/risc-v/src/mpfs/mpfs_dma.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_RISCV_SRC_MPFS_MPFS_DMA_H
+#define __ARCH_RISCV_SRC_MPFS_MPFS_DMA_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <stdint.h>
+#include "mpfs_memorymap.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define MPFS_DMA_NUM_CHANNELS (4)
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+struct mpfs_dma_channel_config
+{
+  uint64_t src_addr;        /* source address */
+  uint64_t dest_addr;       /* destination address */
+  uint64_t num_bytes;       /* Number of bytes to be transfered. (Base-2) */
+  uint8_t  enable_done_int; /* enable transfer complete interrupt */
+  uint8_t  enable_err_int;  /* enable transfer error interrupt */
+  uint8_t  repeat;          /* repeat the transaction */
+  uint8_t  force_order;     /* Enforces strict ordering by only
+                             * allowing one of each transfer type
+                             * in-flight at a time */
+};
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+#ifdef __cplusplus
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+EXTERN int mpfs_dma_setup_transfer(unsigned int channel,
+                                   struct mpfs_dma_channel_config *config);
+EXTERN int mpfs_dma_set_transaction_size(unsigned int channel,
+                                         uint8_t write_size,
+                                         uint8_t read_size);
+EXTERN int mpfs_dma_start(unsigned int channel);
+EXTERN uint32_t mpfs_dma_get_transfer_type(unsigned int channel);
+EXTERN uint64_t mpfs_dma_get_bytes_remaining(unsigned int channel);
+EXTERN uint64_t mpfs_dma_get_current_destination(unsigned int channel);
+EXTERN uint64_t mpfs_dma_get_current_source(unsigned int channel);
+EXTERN int mpfs_dma_get_complete_status(unsigned int channel);
+EXTERN int mpfs_dma_get_error_status(unsigned int channel);
+EXTERN int mpfs_dma_clear_complete_status(unsigned int channel);
+EXTERN int mpfs_dma_clear_error_status(unsigned int channel);
+
+#if defined(__cplusplus)
+}
+#endif
+#undef EXTERN
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ARCH_RISCV_SRC_MPFS_MPFS_DMA_H */