Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/percpu
[pandora-kernel.git] / arch / powerpc / include / asm / fsldma.h
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  */
40 struct 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  */
59 struct 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  */
81 static 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  */
104 static 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  */
125 static 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__ */