Logo Search packages:      
Sourcecode: linux version File versions  Download package

dma.h

/*****************************************************************************
* Copyright 2004 - 2008 Broadcom Corporation.  All rights reserved.
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
* under the terms of the GNU General Public License version 2, available at
* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
*
* Notwithstanding the above, under no circumstances may you combine this
* software in any way with any other Broadcom software provided under a
* license other than the GPL, without Broadcom's express prior written
* consent.
*****************************************************************************/

/****************************************************************************/
/**
*   @file   dma.h
*
*   @brief  API definitions for the linux DMA interface.
*/
/****************************************************************************/

#if !defined(ASM_ARM_ARCH_BCMRING_DMA_H)
#define ASM_ARM_ARCH_BCMRING_DMA_H

/* ---- Include Files ---------------------------------------------------- */

#include <linux/kernel.h>
#include <linux/wait.h>
#include <linux/semaphore.h>
#include <csp/dmacHw.h>
#include <mach/timer.h>
#include <linux/scatterlist.h>
#include <linux/dma-mapping.h>
#include <linux/mm.h>
#include <linux/vmalloc.h>
#include <linux/pagemap.h>

/* ---- Constants and Types ---------------------------------------------- */

/* If DMA_DEBUG_TRACK_RESERVATION is set to a non-zero value, then the filename */
/* and line number of the reservation request will be recorded in the channel table */

#define DMA_DEBUG_TRACK_RESERVATION   1

#define DMA_NUM_CONTROLLERS     2
#define DMA_NUM_CHANNELS        8   /* per controller */

typedef enum {
      DMA_DEVICE_MEM_TO_MEM,  /* For memory to memory transfers */
      DMA_DEVICE_I2S0_DEV_TO_MEM,
      DMA_DEVICE_I2S0_MEM_TO_DEV,
      DMA_DEVICE_I2S1_DEV_TO_MEM,
      DMA_DEVICE_I2S1_MEM_TO_DEV,
      DMA_DEVICE_APM_CODEC_A_DEV_TO_MEM,
      DMA_DEVICE_APM_CODEC_A_MEM_TO_DEV,
      DMA_DEVICE_APM_CODEC_B_DEV_TO_MEM,
      DMA_DEVICE_APM_CODEC_B_MEM_TO_DEV,
      DMA_DEVICE_APM_CODEC_C_DEV_TO_MEM,  /* Additional mic input for beam-forming */
      DMA_DEVICE_APM_PCM0_DEV_TO_MEM,
      DMA_DEVICE_APM_PCM0_MEM_TO_DEV,
      DMA_DEVICE_APM_PCM1_DEV_TO_MEM,
      DMA_DEVICE_APM_PCM1_MEM_TO_DEV,
      DMA_DEVICE_SPUM_DEV_TO_MEM,
      DMA_DEVICE_SPUM_MEM_TO_DEV,
      DMA_DEVICE_SPIH_DEV_TO_MEM,
      DMA_DEVICE_SPIH_MEM_TO_DEV,
      DMA_DEVICE_UART_A_DEV_TO_MEM,
      DMA_DEVICE_UART_A_MEM_TO_DEV,
      DMA_DEVICE_UART_B_DEV_TO_MEM,
      DMA_DEVICE_UART_B_MEM_TO_DEV,
      DMA_DEVICE_PIF_MEM_TO_DEV,
      DMA_DEVICE_PIF_DEV_TO_MEM,
      DMA_DEVICE_ESW_DEV_TO_MEM,
      DMA_DEVICE_ESW_MEM_TO_DEV,
      DMA_DEVICE_VPM_MEM_TO_MEM,
      DMA_DEVICE_CLCD_MEM_TO_MEM,
      DMA_DEVICE_NAND_MEM_TO_MEM,
      DMA_DEVICE_MEM_TO_VRAM,
      DMA_DEVICE_VRAM_TO_MEM,

      /* Add new entries before this line. */

      DMA_NUM_DEVICE_ENTRIES,
      DMA_DEVICE_NONE = 0xff, /* Special value to indicate that no device is currently assigned. */

} DMA_Device_t;

/****************************************************************************
*
*   The DMA_Handle_t is the primary object used by callers of the API.
*
*****************************************************************************/

#define DMA_INVALID_HANDLE  ((DMA_Handle_t) -1)

typedef int DMA_Handle_t;

/****************************************************************************
*
*   The DMA_DescriptorRing_t contains a ring of descriptors which is used
*   to point to regions of memory.
*
*****************************************************************************/

00106 typedef struct {
      void *virtAddr;         /* Virtual Address of the descriptor ring */
      dma_addr_t physAddr;    /* Physical address of the descriptor ring */
      int descriptorsAllocated;     /* Number of descriptors allocated in the descriptor ring */
      size_t bytesAllocated;  /* Number of bytes allocated in the descriptor ring */

} DMA_DescriptorRing_t;

/****************************************************************************
*
*   The DMA_MemType_t and DMA_MemMap_t are helper structures used to setup
*   DMA chains from a variety of memory sources.
*
*****************************************************************************/

#define DMA_MEM_MAP_MIN_SIZE    4096      /* Pages less than this size are better */
                              /* off not being DMA'd. */

typedef enum {
      DMA_MEM_TYPE_NONE,      /* Not a valid setting */
      DMA_MEM_TYPE_VMALLOC,   /* Memory came from vmalloc call */
      DMA_MEM_TYPE_KMALLOC,   /* Memory came from kmalloc call */
      DMA_MEM_TYPE_DMA, /* Memory came from dma_alloc_xxx call */
      DMA_MEM_TYPE_USER,      /* Memory came from user space. */

} DMA_MemType_t;

/* A segment represents a physically and virtually contiguous chunk of memory. */
/* i.e. each segment can be DMA'd */
/* A user of the DMA code will add memory regions. Each region may need to be */
/* represented by one or more segments. */

00138 typedef struct {
      void *virtAddr;         /* Virtual address used for this segment */
      dma_addr_t physAddr;    /* Physical address this segment maps to */
      size_t numBytes;  /* Size of the segment, in bytes */

} DMA_Segment_t;

/* A region represents a virtually contiguous chunk of memory, which may be */
/* made up of multiple segments. */

00148 typedef struct {
      DMA_MemType_t memType;
      void *virtAddr;
      size_t numBytes;

      /* Each region (virtually contiguous) consists of one or more segments. Each */
      /* segment is virtually and physically contiguous. */

      int numSegmentsUsed;
      int numSegmentsAllocated;
      DMA_Segment_t *segment;

      /* When a region corresponds to user memory, we need to lock all of the pages */
      /* down before we can figure out the physical addresses. The lockedPage array contains */
      /* the pages that were locked, and which subsequently need to be unlocked once the */
      /* memory is unmapped. */

      unsigned numLockedPages;
      struct page **lockedPages;

} DMA_Region_t;

00170 typedef struct {
      int inUse;        /* Is this mapping currently being used? */
      struct semaphore lock;  /* Acquired when using this structure */
      enum dma_data_direction dir;  /* Direction this transfer is intended for */

      /* In the event that we're mapping user memory, we need to know which task */
      /* the memory is for, so that we can obtain the correct mm locks. */

      struct task_struct *userTask;

      int numRegionsUsed;
      int numRegionsAllocated;
      DMA_Region_t *region;

} DMA_MemMap_t;

/****************************************************************************
*
*   The DMA_DeviceAttribute_t contains information which describes a
*   particular DMA device (or peripheral).
*
*   It is anticipated that the arrary of DMA_DeviceAttribute_t's will be
*   statically initialized.
*
*****************************************************************************/

/* The device handler is called whenever a DMA operation completes. The reaon */
/* for it to be called will be a bitmask with one or more of the following bits */
/* set. */

#define DMA_HANDLER_REASON_BLOCK_COMPLETE       dmacHw_INTERRUPT_STATUS_BLOCK
#define DMA_HANDLER_REASON_TRANSFER_COMPLETE    dmacHw_INTERRUPT_STATUS_TRANS
#define DMA_HANDLER_REASON_ERROR                dmacHw_INTERRUPT_STATUS_ERROR

typedef void (*DMA_DeviceHandler_t) (DMA_Device_t dev, int reason,
                             void *userData);

#define DMA_DEVICE_FLAG_ON_DMA0             0x00000001
#define DMA_DEVICE_FLAG_ON_DMA1             0x00000002
#define DMA_DEVICE_FLAG_PORT_PER_DMAC       0x00000004      /* If set, it means that the port used on DMAC0 is different from the port used on DMAC1 */
#define DMA_DEVICE_FLAG_ALLOC_DMA1_FIRST    0x00000008      /* If set, allocate from DMA1 before allocating from DMA0 */
#define DMA_DEVICE_FLAG_IS_DEDICATED        0x00000100
#define DMA_DEVICE_FLAG_NO_ISR              0x00000200
#define DMA_DEVICE_FLAG_ALLOW_LARGE_FIFO    0x00000400
#define DMA_DEVICE_FLAG_IN_USE              0x00000800      /* If set, device is in use on a channel */

/* Note: Some DMA devices can be used from multiple DMA Controllers. The bitmask is used to */
/*       determine which DMA controllers a given device can be used from, and the interface */
/*       array determeines the actual interface number to use for a given controller. */

00220 typedef struct {
      uint32_t flags;         /* Bitmask of DMA_DEVICE_FLAG_xxx constants */
      uint8_t dedicatedController;  /* Controller number to use if DMA_DEVICE_FLAG_IS_DEDICATED is set. */
      uint8_t dedicatedChannel;     /* Channel number to use if DMA_DEVICE_FLAG_IS_DEDICATED is set. */
      const char *name; /* Will show up in the /proc entry */

      uint32_t dmacPort[DMA_NUM_CONTROLLERS];   /* Specifies the port number when DMA_DEVICE_FLAG_PORT_PER_DMAC flag is set */

      dmacHw_CONFIG_t config; /* Configuration to use when DMA'ing using this device */

      void *userData;         /* Passed to the devHandler */
      DMA_DeviceHandler_t devHandler;     /* Called when DMA operations finish. */

      timer_tick_count_t transferStartTime;     /* Time the current transfer was started */

      /* The following statistical information will be collected and presented in a proc entry. */
      /* Note: With a contiuous bandwidth of 1 Gb/sec, it would take 584 years to overflow */
      /*       a 64 bit counter. */

      uint64_t numTransfers;  /* Number of DMA transfers performed */
      uint64_t transferTicks; /* Total time spent doing DMA transfers (measured in timer_tick_count_t's) */
      uint64_t transferBytes; /* Total bytes transferred */
      uint32_t timesBlocked;  /* Number of times a channel was unavailable */
      uint32_t numBytes;      /* Last transfer size */

      /* It's not possible to free memory which is allocated for the descriptors from within */
      /* the ISR. So make the presumption that a given device will tend to use the */
      /* same sized buffers over and over again, and we keep them around. */

      DMA_DescriptorRing_t ring;    /* Ring of descriptors allocated for this device */

      /* We stash away some of the information from the previous transfer. If back-to-back */
      /* transfers are performed from the same buffer, then we don't have to keep re-initializing */
      /* the descriptor buffers. */

      uint32_t prevNumBytes;
      dma_addr_t prevSrcData;
      dma_addr_t prevDstData;

} DMA_DeviceAttribute_t;

/****************************************************************************
*
*   DMA_Channel_t, DMA_Controller_t, and DMA_State_t are really internal
*   data structures and don't belong in this header file, but are included
*   merely for discussion.
*
*   By the time this is implemented, these structures will be moved out into
*   the appropriate C source file instead.
*
*****************************************************************************/

/****************************************************************************
*
*   The DMA_Channel_t contains state information about each DMA channel. Some
*   of the channels are dedicated. Non-dedicated channels are shared
*   amongst the other devices.
*
*****************************************************************************/

#define DMA_CHANNEL_FLAG_IN_USE         0x00000001
#define DMA_CHANNEL_FLAG_IS_DEDICATED   0x00000002
#define DMA_CHANNEL_FLAG_NO_ISR         0x00000004
#define DMA_CHANNEL_FLAG_LARGE_FIFO     0x00000008

00285 typedef struct {
      uint32_t flags;         /* bitmask of DMA_CHANNEL_FLAG_xxx constants */
      DMA_Device_t devType;   /* Device this channel is currently reserved for */
      DMA_Device_t lastDevType;     /* Device type that used this previously */
      char name[20];          /* Name passed onto request_irq */

#if (DMA_DEBUG_TRACK_RESERVATION)
      const char *fileName;   /* Place where channel reservation took place */
      int lineNum;            /* Place where channel reservation took place */
#endif
      dmacHw_HANDLE_t dmacHwHandle; /* low level channel handle. */

} DMA_Channel_t;

/****************************************************************************
*
*   The DMA_Controller_t contains state information about each DMA controller.
*
*   The freeChannelQ is stored in the controller data structure rather than
*   the channel data structure since several of the devices are accessible
*   from multiple controllers, and there is no way to know which controller
*   will become available first.
*
*****************************************************************************/

00310 typedef struct {
      DMA_Channel_t channel[DMA_NUM_CHANNELS];

} DMA_Controller_t;

/****************************************************************************
*
*   The DMA_Global_t contains all of the global state information used by
*   the DMA code.
*
*   Callers which need to allocate a shared channel will be queued up
*   on the freeChannelQ until a channel becomes available.
*
*****************************************************************************/

00325 typedef struct {
      struct semaphore lock;  /* acquired when manipulating table entries */
      wait_queue_head_t freeChannelQ;

      DMA_Controller_t controller[DMA_NUM_CONTROLLERS];

} DMA_Global_t;

/* ---- Variable Externs ------------------------------------------------- */

extern DMA_DeviceAttribute_t DMA_gDeviceAttribute[DMA_NUM_DEVICE_ENTRIES];

/* ---- Function Prototypes ---------------------------------------------- */

#if defined(__KERNEL__)

/****************************************************************************/
/**
*   Initializes the DMA module.
*
*   @return
*       0       - Success
*       < 0     - Error
*/
/****************************************************************************/

int dma_init(void);

#if (DMA_DEBUG_TRACK_RESERVATION)
DMA_Handle_t dma_request_channel_dbg(DMA_Device_t dev, const char *fileName,
                             int lineNum);
#define dma_request_channel(dev)  dma_request_channel_dbg(dev, __FILE__, __LINE__)
#else

/****************************************************************************/
/**
*   Reserves a channel for use with @a dev. If the device is setup to use
*   a shared channel, then this function will block until a free channel
*   becomes available.
*
*   @return
*       >= 0    - A valid DMA Handle.
*       -EBUSY  - Device is currently being used.
*       -ENODEV - Device handed in is invalid.
*/
/****************************************************************************/

DMA_Handle_t dma_request_channel(DMA_Device_t dev     /* Device to use with the allocated channel. */
    );
#endif

/****************************************************************************/
/**
*   Frees a previously allocated DMA Handle.
*
*   @return
*        0      - DMA Handle was released successfully.
*       -EINVAL - Invalid DMA handle
*/
/****************************************************************************/

int dma_free_channel(DMA_Handle_t channel /* DMA handle. */
    );

/****************************************************************************/
/**
*   Determines if a given device has been configured as using a shared
*   channel.
*
*   @return boolean
*       0           Device uses a dedicated channel
*       non-zero    Device uses a shared channel
*/
/****************************************************************************/

int dma_device_is_channel_shared(DMA_Device_t dev     /* Device to check. */
    );

/****************************************************************************/
/**
*   Allocates memory to hold a descriptor ring. The descriptor ring then
*   needs to be populated by making one or more calls to
*   dna_add_descriptors.
*
*   The returned descriptor ring will be automatically initialized.
*
*   @return
*       0           Descriptor ring was allocated successfully
*       -ENOMEM     Unable to allocate memory for the desired number of descriptors.
*/
/****************************************************************************/

int dma_alloc_descriptor_ring(DMA_DescriptorRing_t *ring,   /* Descriptor ring to populate */
                        int numDescriptors      /* Number of descriptors that need to be allocated. */
    );

/****************************************************************************/
/**
*   Releases the memory which was previously allocated for a descriptor ring.
*/
/****************************************************************************/

void dma_free_descriptor_ring(DMA_DescriptorRing_t *ring    /* Descriptor to release */
    );

/****************************************************************************/
/**
*   Initializes a descriptor ring, so that descriptors can be added to it.
*   Once a descriptor ring has been allocated, it may be reinitialized for
*   use with additional/different regions of memory.
*
*   Note that if 7 descriptors are allocated, it's perfectly acceptable to
*   initialize the ring with a smaller number of descriptors. The amount
*   of memory allocated for the descriptor ring will not be reduced, and
*   the descriptor ring may be reinitialized later
*
*   @return
*       0           Descriptor ring was initialized successfully
*       -ENOMEM     The descriptor which was passed in has insufficient space
*                   to hold the desired number of descriptors.
*/
/****************************************************************************/

int dma_init_descriptor_ring(DMA_DescriptorRing_t *ring,    /* Descriptor ring to initialize */
                       int numDescriptors /* Number of descriptors to initialize. */
    );

/****************************************************************************/
/**
*   Determines the number of descriptors which would be required for a
*   transfer of the indicated memory region.
*
*   This function also needs to know which DMA device this transfer will
*   be destined for, so that the appropriate DMA configuration can be retrieved.
*   DMA parameters such as transfer width, and whether this is a memory-to-memory
*   or memory-to-peripheral, etc can all affect the actual number of descriptors
*   required.
*
*   @return
*       > 0     Returns the number of descriptors required for the indicated transfer
*       -EINVAL Invalid device type for this kind of transfer
*               (i.e. the device is _MEM_TO_DEV and not _DEV_TO_MEM)
*       -ENOMEM Memory exhausted
*/
/****************************************************************************/

int dma_calculate_descriptor_count(DMA_Device_t device,     /* DMA Device that this will be associated with */
                           dma_addr_t srcData,  /* Place to get data to write to device */
                           dma_addr_t dstData,  /* Pointer to device data address */
                           size_t numBytes      /* Number of bytes to transfer to the device */
    );

/****************************************************************************/
/**
*   Adds a region of memory to the descriptor ring. Note that it may take
*   multiple descriptors for each region of memory. It is the callers
*   responsibility to allocate a sufficiently large descriptor ring.
*
*   @return
*       0       Descriptors were added successfully
*       -EINVAL Invalid device type for this kind of transfer
*               (i.e. the device is _MEM_TO_DEV and not _DEV_TO_MEM)
*       -ENOMEM Memory exhausted
*/
/****************************************************************************/

int dma_add_descriptors(DMA_DescriptorRing_t *ring,   /* Descriptor ring to add descriptors to */
                  DMA_Device_t device,    /* DMA Device that descriptors are for */
                  dma_addr_t srcData,     /* Place to get data (memory or device) */
                  dma_addr_t dstData,     /* Place to put data (memory or device) */
                  size_t numBytes   /* Number of bytes to transfer to the device */
    );

/****************************************************************************/
/**
*   Sets the descriptor ring associated with a device.
*
*   Once set, the descriptor ring will be associated with the device, even
*   across channel request/free calls. Passing in a NULL descriptor ring
*   will release any descriptor ring currently associated with the device.
*
*   Note: If you call dma_transfer, or one of the other dma_alloc_ functions
*         the descriptor ring may be released and reallocated.
*
*   Note: This function will release the descriptor memory for any current
*         descriptor ring associated with this device.
*/
/****************************************************************************/

int dma_set_device_descriptor_ring(DMA_Device_t device,     /* Device to update the descriptor ring for. */
                           DMA_DescriptorRing_t *ring /* Descriptor ring to add descriptors to */
    );

/****************************************************************************/
/**
*   Retrieves the descriptor ring associated with a device.
*/
/****************************************************************************/

int dma_get_device_descriptor_ring(DMA_Device_t device,     /* Device to retrieve the descriptor ring for. */
                           DMA_DescriptorRing_t *ring /* Place to store retrieved ring */
    );

/****************************************************************************/
/**
*   Allocates buffers for the descriptors. This is normally done automatically
*   but needs to be done explicitly when initiating a dma from interrupt
*   context.
*
*   @return
*       0       Descriptors were allocated successfully
*       -EINVAL Invalid device type for this kind of transfer
*               (i.e. the device is _MEM_TO_DEV and not _DEV_TO_MEM)
*       -ENOMEM Memory exhausted
*/
/****************************************************************************/

int dma_alloc_descriptors(DMA_Handle_t handle,  /* DMA Handle */
                    dmacHw_TRANSFER_TYPE_e transferType,    /* Type of transfer being performed */
                    dma_addr_t srcData,   /* Place to get data to write to device */
                    dma_addr_t dstData,   /* Pointer to device data address */
                    size_t numBytes /* Number of bytes to transfer to the device */
    );

/****************************************************************************/
/**
*   Allocates and sets up descriptors for a double buffered circular buffer.
*
*   This is primarily intended to be used for things like the ingress samples
*   from a microphone.
*
*   @return
*       > 0     Number of descriptors actually allocated.
*       -EINVAL Invalid device type for this kind of transfer
*               (i.e. the device is _MEM_TO_DEV and not _DEV_TO_MEM)
*       -ENOMEM Memory exhausted
*/
/****************************************************************************/

int dma_alloc_double_dst_descriptors(DMA_Handle_t handle,   /* DMA Handle */
                             dma_addr_t srcData,      /* Physical address of source data */
                             dma_addr_t dstData1,     /* Physical address of first destination buffer */
                             dma_addr_t dstData2,     /* Physical address of second destination buffer */
                             size_t numBytes    /* Number of bytes in each destination buffer */
    );

/****************************************************************************/
/**
*   Initializes a DMA_MemMap_t data structure
*/
/****************************************************************************/

int dma_init_mem_map(DMA_MemMap_t *memMap /* Stores state information about the map */
    );

/****************************************************************************/
/**
*   Releases any memory currently being held by a memory mapping structure.
*/
/****************************************************************************/

int dma_term_mem_map(DMA_MemMap_t *memMap /* Stores state information about the map */
    );

/****************************************************************************/
/**
*   Looks at a memory address and categorizes it.
*
*   @return One of the values from the DMA_MemType_t enumeration.
*/
/****************************************************************************/

DMA_MemType_t dma_mem_type(void *addr);

/****************************************************************************/
/**
*   Sets the process (aka userTask) associated with a mem map. This is
*   required if user-mode segments will be added to the mapping.
*/
/****************************************************************************/

static inline void dma_mem_map_set_user_task(DMA_MemMap_t *memMap,
                                   struct task_struct *task)
{
      memMap->userTask = task;
}

/****************************************************************************/
/**
*   Looks at a memory address and determines if we support DMA'ing to/from
*   that type of memory.
*
*   @return boolean -
*               return value != 0 means dma supported
*               return value == 0 means dma not supported
*/
/****************************************************************************/

int dma_mem_supports_dma(void *addr);

/****************************************************************************/
/**
*   Initializes a memory map for use. Since this function acquires a
*   sempaphore within the memory map, it is VERY important that dma_unmap
*   be called when you're finished using the map.
*/
/****************************************************************************/

int dma_map_start(DMA_MemMap_t *memMap,   /* Stores state information about the map */
              enum dma_data_direction dir /* Direction that the mapping will be going */
    );

/****************************************************************************/
/**
*   Adds a segment of memory to a memory map.
*
*   @return     0 on success, error code otherwise.
*/
/****************************************************************************/

int dma_map_add_region(DMA_MemMap_t *memMap,    /* Stores state information about the map */
                   void *mem, /* Virtual address that we want to get a map of */
                   size_t numBytes  /* Number of bytes being mapped */
    );

/****************************************************************************/
/**
*   Creates a descriptor ring from a memory mapping.
*
*   @return 0 on success, error code otherwise.
*/
/****************************************************************************/

int dma_map_create_descriptor_ring(DMA_Device_t dev,  /* DMA device (where the ring is stored) */
                           DMA_MemMap_t *memMap,      /* Memory map that will be used */
                           dma_addr_t devPhysAddr     /* Physical address of device */
    );

/****************************************************************************/
/**
*   Maps in a memory region such that it can be used for performing a DMA.
*
*   @return
*/
/****************************************************************************/

int dma_map_mem(DMA_MemMap_t *memMap,     /* Stores state information about the map */
            void *addr, /* Virtual address that we want to get a map of */
            size_t count,     /* Number of bytes being mapped */
            enum dma_data_direction dir   /* Direction that the mapping will be going */
    );

/****************************************************************************/
/**
*   Maps in a memory region such that it can be used for performing a DMA.
*
*   @return
*/
/****************************************************************************/

int dma_unmap(DMA_MemMap_t *memMap, /* Stores state information about the map */
            int dirtied /* non-zero if any of the pages were modified */
    );

/****************************************************************************/
/**
*   Initiates a transfer when the descriptors have already been setup.
*
*   This is a special case, and normally, the dma_transfer_xxx functions should
*   be used.
*
*   @return
*       0       Transfer was started successfully
*       -ENODEV Invalid handle
*/
/****************************************************************************/

int dma_start_transfer(DMA_Handle_t handle);

/****************************************************************************/
/**
*   Stops a previously started DMA transfer.
*
*   @return
*       0       Transfer was stopped successfully
*       -ENODEV Invalid handle
*/
/****************************************************************************/

int dma_stop_transfer(DMA_Handle_t handle);

/****************************************************************************/
/**
*   Waits for a DMA to complete by polling. This function is only intended
*   to be used for testing. Interrupts should be used for most DMA operations.
*/
/****************************************************************************/

int dma_wait_transfer_done(DMA_Handle_t handle);

/****************************************************************************/
/**
*   Initiates a DMA transfer
*
*   @return
*       0       Transfer was started successfully
*       -EINVAL Invalid device type for this kind of transfer
*               (i.e. the device is _MEM_TO_DEV and not _DEV_TO_MEM)
*/
/****************************************************************************/

int dma_transfer(DMA_Handle_t handle,     /* DMA Handle */
             dmacHw_TRANSFER_TYPE_e transferType,     /* Type of transfer being performed */
             dma_addr_t srcData,    /* Place to get data to write to device */
             dma_addr_t dstData,    /* Pointer to device data address */
             size_t numBytes  /* Number of bytes to transfer to the device */
    );

/****************************************************************************/
/**
*   Initiates a transfer from memory to a device.
*
*   @return
*       0       Transfer was started successfully
*       -EINVAL Invalid device type for this kind of transfer
*               (i.e. the device is _DEV_TO_MEM and not _MEM_TO_DEV)
*/
/****************************************************************************/

static inline int dma_transfer_to_device(DMA_Handle_t handle,     /* DMA Handle */
                               dma_addr_t srcData,    /* Place to get data to write to device (physical address) */
                               dma_addr_t dstData,    /* Pointer to device data address (physical address) */
                               size_t numBytes  /* Number of bytes to transfer to the device */
    ) {
      return dma_transfer(handle,
                      dmacHw_TRANSFER_TYPE_MEM_TO_PERIPHERAL,
                      srcData, dstData, numBytes);
}

/****************************************************************************/
/**
*   Initiates a transfer from a device to memory.
*
*   @return
*       0       Transfer was started successfully
*       -EINVAL Invalid device type for this kind of transfer
*               (i.e. the device is _MEM_TO_DEV and not _DEV_TO_MEM)
*/
/****************************************************************************/

static inline int dma_transfer_from_device(DMA_Handle_t handle,   /* DMA Handle */
                                 dma_addr_t srcData,  /* Pointer to the device data address (physical address) */
                                 dma_addr_t dstData,  /* Place to store data retrieved from the device (physical address) */
                                 size_t numBytes      /* Number of bytes to retrieve from the device */
    ) {
      return dma_transfer(handle,
                      dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM,
                      srcData, dstData, numBytes);
}

/****************************************************************************/
/**
*   Initiates a memory to memory transfer.
*
*   @return
*       0       Transfer was started successfully
*       -EINVAL Invalid device type for this kind of transfer
*               (i.e. the device wasn't DMA_DEVICE_MEM_TO_MEM)
*/
/****************************************************************************/

static inline int dma_transfer_mem_to_mem(DMA_Handle_t handle,    /* DMA Handle */
                                dma_addr_t srcData,   /* Place to transfer data from (physical address) */
                                dma_addr_t dstData,   /* Place to transfer data to (physical address) */
                                size_t numBytes /* Number of bytes to transfer */
    ) {
      return dma_transfer(handle,
                      dmacHw_TRANSFER_TYPE_MEM_TO_MEM,
                      srcData, dstData, numBytes);
}

/****************************************************************************/
/**
*   Set the callback function which will be called when a transfer completes.
*   If a NULL callback function is set, then no callback will occur.
*
*   @note   @a devHandler will be called from IRQ context.
*
*   @return
*       0       - Success
*       -ENODEV - Device handed in is invalid.
*/
/****************************************************************************/

int dma_set_device_handler(DMA_Device_t dev,    /* Device to set the callback for. */
                     DMA_DeviceHandler_t devHandler,  /* Function to call when the DMA completes */
                     void *userData /* Pointer which will be passed to devHandler. */
    );

#endif

#endif /* ASM_ARM_ARCH_BCMRING_DMA_H */

Generated by  Doxygen 1.6.0   Back to index