]>
Commit | Line | Data |
---|---|---|
bbea0b6e IS |
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 | ||
94131e17 | 14 | #include <linux/slab.h> |
bbea0b6e IS |
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__ */ |