-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Use the DMA_SLAVE capability of the DMAEngine API to copy/from a scatterlist into an arbitrary list of hardware address/length pairs. This allows a single DMA transaction to copy data from several different devices into a scatterlist at the same time. This also adds support to enable some controller-specific features such as external start and external pause for a DMA transaction. [dan.j.williams@intel.com: rebased on tx_list movement] Signed-off-by: Ira W. Snyder <iws@ovro.caltech.edu> Acked-by: Li Yang <leoli@freescale.com> Acked-by: Kumar Gala <galak@kernel.crashing.org> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
- Loading branch information
Ira Snyder
authored and
Dan Williams
committed
Sep 9, 2009
1 parent
e6c7ecb
commit bbea0b6
Showing
2 changed files
with
363 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
/* | ||
* Freescale MPC83XX / MPC85XX DMA Controller | ||
* | ||
* Copyright (c) 2009 Ira W. Snyder <iws@ovro.caltech.edu> | ||
* | ||
* This file is licensed under the terms of the GNU General Public License | ||
* version 2. This program is licensed "as is" without any warranty of any | ||
* kind, whether express or implied. | ||
*/ | ||
|
||
#ifndef __ARCH_POWERPC_ASM_FSLDMA_H__ | ||
#define __ARCH_POWERPC_ASM_FSLDMA_H__ | ||
|
||
#include <linux/dmaengine.h> | ||
|
||
/* | ||
* Definitions for the Freescale DMA controller's DMA_SLAVE implemention | ||
* | ||
* The Freescale DMA_SLAVE implementation was designed to handle many-to-many | ||
* transfers. An example usage would be an accelerated copy between two | ||
* scatterlists. Another example use would be an accelerated copy from | ||
* multiple non-contiguous device buffers into a single scatterlist. | ||
* | ||
* A DMA_SLAVE transaction is defined by a struct fsl_dma_slave. This | ||
* structure contains a list of hardware addresses that should be copied | ||
* to/from the scatterlist passed into device_prep_slave_sg(). The structure | ||
* also has some fields to enable hardware-specific features. | ||
*/ | ||
|
||
/** | ||
* struct fsl_dma_hw_addr | ||
* @entry: linked list entry | ||
* @address: the hardware address | ||
* @length: length to transfer | ||
* | ||
* Holds a single physical hardware address / length pair for use | ||
* with the DMAEngine DMA_SLAVE API. | ||
*/ | ||
struct fsl_dma_hw_addr { | ||
struct list_head entry; | ||
|
||
dma_addr_t address; | ||
size_t length; | ||
}; | ||
|
||
/** | ||
* struct fsl_dma_slave | ||
* @addresses: a linked list of struct fsl_dma_hw_addr structures | ||
* @request_count: value for DMA request count | ||
* @src_loop_size: setup and enable constant source-address DMA transfers | ||
* @dst_loop_size: setup and enable constant destination address DMA transfers | ||
* @external_start: enable externally started DMA transfers | ||
* @external_pause: enable externally paused DMA transfers | ||
* | ||
* Holds a list of address / length pairs for use with the DMAEngine | ||
* DMA_SLAVE API implementation for the Freescale DMA controller. | ||
*/ | ||
struct fsl_dma_slave { | ||
|
||
/* List of hardware address/length pairs */ | ||
struct list_head addresses; | ||
|
||
/* Support for extra controller features */ | ||
unsigned int request_count; | ||
unsigned int src_loop_size; | ||
unsigned int dst_loop_size; | ||
bool external_start; | ||
bool external_pause; | ||
}; | ||
|
||
/** | ||
* fsl_dma_slave_append - add an address/length pair to a struct fsl_dma_slave | ||
* @slave: the &struct fsl_dma_slave to add to | ||
* @address: the hardware address to add | ||
* @length: the length of bytes to transfer from @address | ||
* | ||
* Add a hardware address/length pair to a struct fsl_dma_slave. Returns 0 on | ||
* success, -ERRNO otherwise. | ||
*/ | ||
static inline int fsl_dma_slave_append(struct fsl_dma_slave *slave, | ||
dma_addr_t address, size_t length) | ||
{ | ||
struct fsl_dma_hw_addr *addr; | ||
|
||
addr = kzalloc(sizeof(*addr), GFP_ATOMIC); | ||
if (!addr) | ||
return -ENOMEM; | ||
|
||
INIT_LIST_HEAD(&addr->entry); | ||
addr->address = address; | ||
addr->length = length; | ||
|
||
list_add_tail(&addr->entry, &slave->addresses); | ||
return 0; | ||
} | ||
|
||
/** | ||
* fsl_dma_slave_free - free a struct fsl_dma_slave | ||
* @slave: the struct fsl_dma_slave to free | ||
* | ||
* Free a struct fsl_dma_slave and all associated address/length pairs | ||
*/ | ||
static inline void fsl_dma_slave_free(struct fsl_dma_slave *slave) | ||
{ | ||
struct fsl_dma_hw_addr *addr, *tmp; | ||
|
||
if (slave) { | ||
list_for_each_entry_safe(addr, tmp, &slave->addresses, entry) { | ||
list_del(&addr->entry); | ||
kfree(addr); | ||
} | ||
|
||
kfree(slave); | ||
} | ||
} | ||
|
||
/** | ||
* fsl_dma_slave_alloc - allocate a struct fsl_dma_slave | ||
* @gfp: the flags to pass to kmalloc when allocating this structure | ||
* | ||
* Allocate a struct fsl_dma_slave for use by the DMA_SLAVE API. Returns a new | ||
* struct fsl_dma_slave on success, or NULL on failure. | ||
*/ | ||
static inline struct fsl_dma_slave *fsl_dma_slave_alloc(gfp_t gfp) | ||
{ | ||
struct fsl_dma_slave *slave; | ||
|
||
slave = kzalloc(sizeof(*slave), gfp); | ||
if (!slave) | ||
return NULL; | ||
|
||
INIT_LIST_HEAD(&slave->addresses); | ||
return slave; | ||
} | ||
|
||
#endif /* __ARCH_POWERPC_ASM_FSLDMA_H__ */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters