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