|  | /* | 
|  | * 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__ */ |