1/* 2 * Freescale MPC83XX / MPC85XX DMA Controller 3 * 4 * Copyright (c) 2009 Ira W. Snyder <iws@ovro.caltech.edu> 5 * 6 * This file is licensed under the terms of the GNU General Public License 7 * version 2. This program is licensed "as is" without any warranty of any 8 * kind, whether express or implied. 9 */ 10 11#ifndef __ARCH_POWERPC_ASM_FSLDMA_H__ 12#define __ARCH_POWERPC_ASM_FSLDMA_H__ 13 14#include <linux/dmaengine.h> 15 16/* 17 * Definitions for the Freescale DMA controller's DMA_SLAVE implemention 18 * 19 * The Freescale DMA_SLAVE implementation was designed to handle many-to-many 20 * transfers. An example usage would be an accelerated copy between two 21 * scatterlists. Another example use would be an accelerated copy from 22 * multiple non-contiguous device buffers into a single scatterlist. 23 * 24 * A DMA_SLAVE transaction is defined by a struct fsl_dma_slave. This 25 * structure contains a list of hardware addresses that should be copied 26 * to/from the scatterlist passed into device_prep_slave_sg(). The structure 27 * also has some fields to enable hardware-specific features. 28 */ 29 30/** 31 * struct fsl_dma_hw_addr 32 * @entry: linked list entry 33 * @address: the hardware address 34 * @length: length to transfer 35 * 36 * Holds a single physical hardware address / length pair for use 37 * with the DMAEngine DMA_SLAVE API. 38 */ 39struct fsl_dma_hw_addr { 40 struct list_head entry; 41 42 dma_addr_t address; 43 size_t length; 44}; 45 46/** 47 * struct fsl_dma_slave 48 * @addresses: a linked list of struct fsl_dma_hw_addr structures 49 * @request_count: value for DMA request count 50 * @src_loop_size: setup and enable constant source-address DMA transfers 51 * @dst_loop_size: setup and enable constant destination address DMA transfers 52 * @external_start: enable externally started DMA transfers 53 * @external_pause: enable externally paused DMA transfers 54 * 55 * Holds a list of address / length pairs for use with the DMAEngine 56 * DMA_SLAVE API implementation for the Freescale DMA controller. 57 */ 58struct fsl_dma_slave { 59 60 /* List of hardware address/length pairs */ 61 struct list_head addresses; 62 63 /* Support for extra controller features */ 64 unsigned int request_count; 65 unsigned int src_loop_size; 66 unsigned int dst_loop_size; 67 bool external_start; 68 bool external_pause; 69}; 70 71/** 72 * fsl_dma_slave_append - add an address/length pair to a struct fsl_dma_slave 73 * @slave: the &struct fsl_dma_slave to add to 74 * @address: the hardware address to add 75 * @length: the length of bytes to transfer from @address 76 * 77 * Add a hardware address/length pair to a struct fsl_dma_slave. Returns 0 on 78 * success, -ERRNO otherwise. 79 */ 80static inline int fsl_dma_slave_append(struct fsl_dma_slave *slave, 81 dma_addr_t address, size_t length) 82{ 83 struct fsl_dma_hw_addr *addr; 84 85 addr = kzalloc(sizeof(*addr), GFP_ATOMIC); 86 if (!addr) 87 return -ENOMEM; 88 89 INIT_LIST_HEAD(&addr->entry); 90 addr->address = address; 91 addr->length = length; 92 93 list_add_tail(&addr->entry, &slave->addresses); 94 return 0; 95} 96 97/** 98 * fsl_dma_slave_free - free a struct fsl_dma_slave 99 * @slave: the struct fsl_dma_slave to free 100 * 101 * Free a struct fsl_dma_slave and all associated address/length pairs 102 */ 103static inline void fsl_dma_slave_free(struct fsl_dma_slave *slave) 104{ 105 struct fsl_dma_hw_addr *addr, *tmp; 106 107 if (slave) { 108 list_for_each_entry_safe(addr, tmp, &slave->addresses, entry) { 109 list_del(&addr->entry); 110 kfree(addr); 111 } 112 113 kfree(slave); 114 } 115} 116 117/** 118 * fsl_dma_slave_alloc - allocate a struct fsl_dma_slave 119 * @gfp: the flags to pass to kmalloc when allocating this structure 120 * 121 * Allocate a struct fsl_dma_slave for use by the DMA_SLAVE API. Returns a new 122 * struct fsl_dma_slave on success, or NULL on failure. 123 */ 124static inline struct fsl_dma_slave *fsl_dma_slave_alloc(gfp_t gfp) 125{ 126 struct fsl_dma_slave *slave; 127 128 slave = kzalloc(sizeof(*slave), gfp); 129 if (!slave) 130 return NULL; 131 132 INIT_LIST_HEAD(&slave->addresses); 133 return slave; 134} 135 136#endif /* __ARCH_POWERPC_ASM_FSLDMA_H__ */ 137