From 596f52c3eeee5f2380a76d07ec4a64928332c73c Mon Sep 17 00:00:00 2001 From: ZhongAn Date: Wed, 28 Mar 2018 15:30:23 +0800 Subject: [PATCH] Nuttx/dma: add dma framework for nuttx Signed-off-by: ZhongAn Signed-off-by: dongjiuzhu1 --- drivers/Kconfig | 1 + drivers/Makefile | 1 + drivers/dma/Kconfig | 18 +++ drivers/dma/Make.defs | 29 +++++ include/nuttx/dma/dma.h | 266 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 315 insertions(+) create mode 100644 drivers/dma/Kconfig create mode 100644 drivers/dma/Make.defs create mode 100644 include/nuttx/dma/dma.h diff --git a/drivers/Kconfig b/drivers/Kconfig index b99463cc2d..50487c6c51 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -53,3 +53,4 @@ source "drivers/motor/Kconfig" source "drivers/math/Kconfig" source "drivers/segger/Kconfig" source "drivers/usrsock/Kconfig" +source "drivers/dma/Kconfig" diff --git a/drivers/Makefile b/drivers/Makefile index f7b35ac9e4..b2dea19048 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -32,6 +32,7 @@ include bch/Make.defs include can/Make.defs include clk/Make.defs include crypto/Make.defs +include dma/Make.defs include math/Make.defs include motor/Make.defs include i2c/Make.defs diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig new file mode 100644 index 0000000000..915c919c39 --- /dev/null +++ b/drivers/dma/Kconfig @@ -0,0 +1,18 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +menuconfig DMA + bool "DMA driver interfaces" + default n + select ARCH_DMA + ---help--- + Drivers for various DMA devices. + +if DMA + +config DMA_LINK + bool "Support DMA link configure" + +endif diff --git a/drivers/dma/Make.defs b/drivers/dma/Make.defs new file mode 100644 index 0000000000..7066ea51a9 --- /dev/null +++ b/drivers/dma/Make.defs @@ -0,0 +1,29 @@ +############################################################################ +# drivers/dma/Make.defs +# +# 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. +# +############################################################################ + +# Include dma driver build support + +ifeq ($(CONFIG_DMA),y) + +DEPPATH += --dep-path dma +VPATH += :dma +CFLAGS += ${INCDIR_PREFIX}$(TOPDIR)$(DELIM)drivers$(DELIM)dma + +endif # CONFIG_DMA diff --git a/include/nuttx/dma/dma.h b/include/nuttx/dma/dma.h new file mode 100644 index 0000000000..9825a149cc --- /dev/null +++ b/include/nuttx/dma/dma.h @@ -0,0 +1,266 @@ +/**************************************************************************** + * include/nuttx/dma/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 __INCLUDE_NUTTX_DMA_DMA_H +#define __INCLUDE_NUTTX_DMA_DMA_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* DMA transfer direction indicator */ + +#define DMA_MEM_TO_MEM 1 +#define DMA_MEM_TO_DEV 2 +#define DMA_DEV_TO_MEM 3 +#define DMA_DEV_TO_DEV 4 + +/**************************************************************************** + * Name: DMA_GET_CHAN + * + * Description: + * Get a DMA channel. This function gives the caller mutually exclusive + * access to the DMA channel specified by the 'ident' argument. + * + * If the DMA channel is not available, then DMA_GET_CHAN will wait + * until the holder of the channel relinquishes the channel by calling + * DMA_PUT_CHAN(). WARNING: If you have two devices sharing a DMA + * channel and the code never releases the channel, the DMA_GET_CHAN + * call for the other will hang forever in this function! + * + * Input Parameters: + * ident - Identifies the channel resource + * + * Returned Value: + * Provided that 'ident' is valid, this function ALWAYS returns a non-NULL, + * dma_chan_s instance. (If 'ident' is invalid, the function will assert + * if debug is enabled or do something ignorant otherwise). + * + ****************************************************************************/ + +#define DMA_GET_CHAN(dev, ident) (dev)->get_chan(dev, ident) + +/**************************************************************************** + * Name: DMA_PUT_CHAN + * + * Description: + * Release a DMA channel. If another thread is waiting for this DMA channel + * in a call to DMA_GET_CHAN, then this function will re-assign the DMA + * channel to that thread and wake it up. NOTE: The 'chan' used in this + * argument must NEVER be used again until DMA_GET_CHAN() is called again + * to re-gain access to the channel. + * + * Returned Value: + * None + * + ****************************************************************************/ + +#define DMA_PUT_CHAN(dev, chan) (dev)->put_chan(dev, chan) + +/**************************************************************************** + * Name: DMA_CONFIG + * + * Description: + * Configure DMA before using + * + ****************************************************************************/ + +#define DMA_CONFIG(chan, cfg) (chan)->ops->config(chan, cfg) + +/**************************************************************************** + * Name: DMA_START + * + * Description: + * Start the DMA transfer. NOTE: The DMA module does *NOT* perform any + * cache operations. It is the responsibility of the DMA client to clean + * DMA buffers after staring of the DMA TX operations. + * + * Input Parameters: + * chan - The channel to start + * callback - The callback when the transfer finish + * arg - The argument will pass to callback + * dst - The destination address + * src - The source address + * len - The length to transfer + * + * Returned Value: + * The error code + * + ****************************************************************************/ + +#define DMA_START(chan, callback, arg, dst, src, len) \ + (chan)->ops->start(chan, callback, arg, dst, src, len) + +/**************************************************************************** + * Name: DMA_START_CYCLIC + * + * Description: + * Start the cyclic DMA transfer. + * + * Note: callback get called for each period length data DMA transfer. + * + ****************************************************************************/ + +#define DMA_START_CYCLIC(chan, callback, arg, dst, src, len, period_len) \ + (chan)->ops->start_cyclic(chan, callback, arg, dst, src, len, period_len) + +/**************************************************************************** + * Name: DMA_PAUSE + * + * Description: + * Pause the DMA transfer. After DMA_PAUSE() is called, DMA_RESUME() must + * be called to restart the transfer again. + * + ****************************************************************************/ + +#define DMA_PAUSE(chan) (chan)->ops->pause(chan) + +/**************************************************************************** + * Name: DMA_RESUME + * + * Description: + * Resume the DMA transfer. + * + ****************************************************************************/ + +#define DMA_RESUME(chan) (chan)->ops->resume(chan) + +/**************************************************************************** + * Name: DMA_STOP + * + * Description: + * Stop the DMA transfer. + * + ****************************************************************************/ + +#define DMA_STOP(chan) (chan)->ops->stop(chan) + +/**************************************************************************** + * Name: DMA_RESIDUAL + * + * Description: + * Returns the number of bytes remaining to be transferred. + * + ****************************************************************************/ + +#define DMA_RESIDUAL(chan) (chan)->ops->residual(chan) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * This is the type of the callback that is used to inform the user of the + * completion of the DMA. NOTE: The DMA module does *NOT* perform any cache + * operations. It is the responsibility of the DMA client to invalidate DMA + * buffers after completion of the DMA RX operations. + * + * Input Parameters: + * chan - Refers to the DMA channel. + * arg - A user-provided value that was provided when start() was called. + * len - Positive value represent the transfer length, negative is error + * code. + * + * Returned Value: + * None + * + ****************************************************************************/ + +struct dma_chan_s; +typedef CODE void (*dma_callback_t)(FAR struct dma_chan_s *chan, + FAR void *arg, ssize_t len); + +/* This struct is passed in as configuration data to a DMA engine + * in order to set up a certain channel for DMA transport at runtime. + * + * The rationale for adding configuration information to this struct is as + * follows: if it is likely that more than one DMA controllers in the world + * will support the configuration option, then make it generic. If not: if + * it is fixed so that it be sent in static from the platform data, then + * prefer to do that. + * + * direction - whether the data shall go in or out on this channel. + * priority - the bus priority compare with other active channel. + * timeout - abort if the source can't prepare data within this value. + * dst_width - this is the width in bytes of destination target(TX) register + * where DMA data shall be read. If the source is memory this + * may be ignored. Legal values: 1, 2, 4, 8. + * src_width - same as dst_width but for the source(RX) mutatis mutandis. + * + * Note: the special value zero means to keep the current value without + * change. + * + ****************************************************************************/ + +struct dma_config_s +{ + unsigned int direction; + unsigned int priority; + unsigned int timeout; + unsigned int dst_width; + unsigned int src_width; +}; + +/* The DMA vtable */ + +struct dma_ops_s +{ + CODE int (*config)(FAR struct dma_chan_s *chan, + FAR const struct dma_config_s *cfg); + CODE int (*start)(FAR struct dma_chan_s *chan, + dma_callback_t callback, FAR void *arg, + uintptr_t dst, uintptr_t src, size_t len); + CODE int (*start_cyclic)(FAR struct dma_chan_s *chan, + dma_callback_t callback, FAR void *arg, + uintptr_t dst, uintptr_t src, + size_t len, size_t period_len); + CODE int (*stop)(FAR struct dma_chan_s *chan); + CODE int (*pause)(FAR struct dma_chan_s *chan); + CODE int (*resume)(FAR struct dma_chan_s *chan); + CODE size_t (*residual)(FAR struct dma_chan_s *chan); +}; + +/* This structure only defines the initial fields of the structure + * visible to the DMA client. The specific implementation may add + * additional device specific fields after the vtable. + */ + +struct dma_chan_s +{ + FAR const struct dma_ops_s *ops; +}; + +struct dma_dev_s +{ + CODE FAR struct dma_chan_s *(*get_chan)(FAR struct dma_dev_s *dev, + unsigned int ident); + CODE void (*put_chan)(FAR struct dma_dev_s *dev, + FAR struct dma_chan_s *chan); +}; + +#endif /* __INCLUDE_NUTTX_DMA_DMA_H */