diff options
Diffstat (limited to 'arch/arm/mach-bcmring/include')
-rw-r--r-- | arch/arm/mach-bcmring/include/mach/dma.h | 826 |
1 files changed, 826 insertions, 0 deletions
diff --git a/arch/arm/mach-bcmring/include/mach/dma.h b/arch/arm/mach-bcmring/include/mach/dma.h new file mode 100644 index 000000000000..847980c85c88 --- /dev/null +++ b/arch/arm/mach-bcmring/include/mach/dma.h | |||
@@ -0,0 +1,826 @@ | |||
1 | /***************************************************************************** | ||
2 | * Copyright 2004 - 2008 Broadcom Corporation. All rights reserved. | ||
3 | * | ||
4 | * Unless you and Broadcom execute a separate written software license | ||
5 | * agreement governing use of this software, this software is licensed to you | ||
6 | * under the terms of the GNU General Public License version 2, available at | ||
7 | * http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). | ||
8 | * | ||
9 | * Notwithstanding the above, under no circumstances may you combine this | ||
10 | * software in any way with any other Broadcom software provided under a | ||
11 | * license other than the GPL, without Broadcom's express prior written | ||
12 | * consent. | ||
13 | *****************************************************************************/ | ||
14 | |||
15 | /****************************************************************************/ | ||
16 | /** | ||
17 | * @file dma.h | ||
18 | * | ||
19 | * @brief API definitions for the linux DMA interface. | ||
20 | */ | ||
21 | /****************************************************************************/ | ||
22 | |||
23 | #if !defined(ASM_ARM_ARCH_BCMRING_DMA_H) | ||
24 | #define ASM_ARM_ARCH_BCMRING_DMA_H | ||
25 | |||
26 | /* ---- Include Files ---------------------------------------------------- */ | ||
27 | |||
28 | #include <linux/kernel.h> | ||
29 | #include <linux/wait.h> | ||
30 | #include <linux/semaphore.h> | ||
31 | #include <csp/dmacHw.h> | ||
32 | #include <mach/timer.h> | ||
33 | #include <linux/scatterlist.h> | ||
34 | #include <linux/dma-mapping.h> | ||
35 | #include <linux/mm.h> | ||
36 | #include <linux/vmalloc.h> | ||
37 | #include <linux/pagemap.h> | ||
38 | |||
39 | /* ---- Constants and Types ---------------------------------------------- */ | ||
40 | |||
41 | /* If DMA_DEBUG_TRACK_RESERVATION is set to a non-zero value, then the filename */ | ||
42 | /* and line number of the reservation request will be recorded in the channel table */ | ||
43 | |||
44 | #define DMA_DEBUG_TRACK_RESERVATION 1 | ||
45 | |||
46 | #define DMA_NUM_CONTROLLERS 2 | ||
47 | #define DMA_NUM_CHANNELS 8 /* per controller */ | ||
48 | |||
49 | typedef enum { | ||
50 | DMA_DEVICE_MEM_TO_MEM, /* For memory to memory transfers */ | ||
51 | DMA_DEVICE_I2S0_DEV_TO_MEM, | ||
52 | DMA_DEVICE_I2S0_MEM_TO_DEV, | ||
53 | DMA_DEVICE_I2S1_DEV_TO_MEM, | ||
54 | DMA_DEVICE_I2S1_MEM_TO_DEV, | ||
55 | DMA_DEVICE_APM_CODEC_A_DEV_TO_MEM, | ||
56 | DMA_DEVICE_APM_CODEC_A_MEM_TO_DEV, | ||
57 | DMA_DEVICE_APM_CODEC_B_DEV_TO_MEM, | ||
58 | DMA_DEVICE_APM_CODEC_B_MEM_TO_DEV, | ||
59 | DMA_DEVICE_APM_CODEC_C_DEV_TO_MEM, /* Additional mic input for beam-forming */ | ||
60 | DMA_DEVICE_APM_PCM0_DEV_TO_MEM, | ||
61 | DMA_DEVICE_APM_PCM0_MEM_TO_DEV, | ||
62 | DMA_DEVICE_APM_PCM1_DEV_TO_MEM, | ||
63 | DMA_DEVICE_APM_PCM1_MEM_TO_DEV, | ||
64 | DMA_DEVICE_SPUM_DEV_TO_MEM, | ||
65 | DMA_DEVICE_SPUM_MEM_TO_DEV, | ||
66 | DMA_DEVICE_SPIH_DEV_TO_MEM, | ||
67 | DMA_DEVICE_SPIH_MEM_TO_DEV, | ||
68 | DMA_DEVICE_UART_A_DEV_TO_MEM, | ||
69 | DMA_DEVICE_UART_A_MEM_TO_DEV, | ||
70 | DMA_DEVICE_UART_B_DEV_TO_MEM, | ||
71 | DMA_DEVICE_UART_B_MEM_TO_DEV, | ||
72 | DMA_DEVICE_PIF_MEM_TO_DEV, | ||
73 | DMA_DEVICE_PIF_DEV_TO_MEM, | ||
74 | DMA_DEVICE_ESW_DEV_TO_MEM, | ||
75 | DMA_DEVICE_ESW_MEM_TO_DEV, | ||
76 | DMA_DEVICE_VPM_MEM_TO_MEM, | ||
77 | DMA_DEVICE_CLCD_MEM_TO_MEM, | ||
78 | DMA_DEVICE_NAND_MEM_TO_MEM, | ||
79 | DMA_DEVICE_MEM_TO_VRAM, | ||
80 | DMA_DEVICE_VRAM_TO_MEM, | ||
81 | |||
82 | /* Add new entries before this line. */ | ||
83 | |||
84 | DMA_NUM_DEVICE_ENTRIES, | ||
85 | DMA_DEVICE_NONE = 0xff, /* Special value to indicate that no device is currently assigned. */ | ||
86 | |||
87 | } DMA_Device_t; | ||
88 | |||
89 | /**************************************************************************** | ||
90 | * | ||
91 | * The DMA_Handle_t is the primary object used by callers of the API. | ||
92 | * | ||
93 | *****************************************************************************/ | ||
94 | |||
95 | #define DMA_INVALID_HANDLE ((DMA_Handle_t) -1) | ||
96 | |||
97 | typedef int DMA_Handle_t; | ||
98 | |||
99 | /**************************************************************************** | ||
100 | * | ||
101 | * The DMA_DescriptorRing_t contains a ring of descriptors which is used | ||
102 | * to point to regions of memory. | ||
103 | * | ||
104 | *****************************************************************************/ | ||
105 | |||
106 | typedef struct { | ||
107 | void *virtAddr; /* Virtual Address of the descriptor ring */ | ||
108 | dma_addr_t physAddr; /* Physical address of the descriptor ring */ | ||
109 | int descriptorsAllocated; /* Number of descriptors allocated in the descriptor ring */ | ||
110 | size_t bytesAllocated; /* Number of bytes allocated in the descriptor ring */ | ||
111 | |||
112 | } DMA_DescriptorRing_t; | ||
113 | |||
114 | /**************************************************************************** | ||
115 | * | ||
116 | * The DMA_MemType_t and DMA_MemMap_t are helper structures used to setup | ||
117 | * DMA chains from a variety of memory sources. | ||
118 | * | ||
119 | *****************************************************************************/ | ||
120 | |||
121 | #define DMA_MEM_MAP_MIN_SIZE 4096 /* Pages less than this size are better */ | ||
122 | /* off not being DMA'd. */ | ||
123 | |||
124 | typedef enum { | ||
125 | DMA_MEM_TYPE_NONE, /* Not a valid setting */ | ||
126 | DMA_MEM_TYPE_VMALLOC, /* Memory came from vmalloc call */ | ||
127 | DMA_MEM_TYPE_KMALLOC, /* Memory came from kmalloc call */ | ||
128 | DMA_MEM_TYPE_DMA, /* Memory came from dma_alloc_xxx call */ | ||
129 | DMA_MEM_TYPE_USER, /* Memory came from user space. */ | ||
130 | |||
131 | } DMA_MemType_t; | ||
132 | |||
133 | /* A segment represents a physically and virtually contiguous chunk of memory. */ | ||
134 | /* i.e. each segment can be DMA'd */ | ||
135 | /* A user of the DMA code will add memory regions. Each region may need to be */ | ||
136 | /* represented by one or more segments. */ | ||
137 | |||
138 | typedef struct { | ||
139 | void *virtAddr; /* Virtual address used for this segment */ | ||
140 | dma_addr_t physAddr; /* Physical address this segment maps to */ | ||
141 | size_t numBytes; /* Size of the segment, in bytes */ | ||
142 | |||
143 | } DMA_Segment_t; | ||
144 | |||
145 | /* A region represents a virtually contiguous chunk of memory, which may be */ | ||
146 | /* made up of multiple segments. */ | ||
147 | |||
148 | typedef struct { | ||
149 | DMA_MemType_t memType; | ||
150 | void *virtAddr; | ||
151 | size_t numBytes; | ||
152 | |||
153 | /* Each region (virtually contiguous) consists of one or more segments. Each */ | ||
154 | /* segment is virtually and physically contiguous. */ | ||
155 | |||
156 | int numSegmentsUsed; | ||
157 | int numSegmentsAllocated; | ||
158 | DMA_Segment_t *segment; | ||
159 | |||
160 | /* When a region corresponds to user memory, we need to lock all of the pages */ | ||
161 | /* down before we can figure out the physical addresses. The lockedPage array contains */ | ||
162 | /* the pages that were locked, and which subsequently need to be unlocked once the */ | ||
163 | /* memory is unmapped. */ | ||
164 | |||
165 | unsigned numLockedPages; | ||
166 | struct page **lockedPages; | ||
167 | |||
168 | } DMA_Region_t; | ||
169 | |||
170 | typedef struct { | ||
171 | int inUse; /* Is this mapping currently being used? */ | ||
172 | struct semaphore lock; /* Acquired when using this structure */ | ||
173 | enum dma_data_direction dir; /* Direction this transfer is intended for */ | ||
174 | |||
175 | /* In the event that we're mapping user memory, we need to know which task */ | ||
176 | /* the memory is for, so that we can obtain the correct mm locks. */ | ||
177 | |||
178 | struct task_struct *userTask; | ||
179 | |||
180 | int numRegionsUsed; | ||
181 | int numRegionsAllocated; | ||
182 | DMA_Region_t *region; | ||
183 | |||
184 | } DMA_MemMap_t; | ||
185 | |||
186 | /**************************************************************************** | ||
187 | * | ||
188 | * The DMA_DeviceAttribute_t contains information which describes a | ||
189 | * particular DMA device (or peripheral). | ||
190 | * | ||
191 | * It is anticipated that the arrary of DMA_DeviceAttribute_t's will be | ||
192 | * statically initialized. | ||
193 | * | ||
194 | *****************************************************************************/ | ||
195 | |||
196 | /* The device handler is called whenever a DMA operation completes. The reaon */ | ||
197 | /* for it to be called will be a bitmask with one or more of the following bits */ | ||
198 | /* set. */ | ||
199 | |||
200 | #define DMA_HANDLER_REASON_BLOCK_COMPLETE dmacHw_INTERRUPT_STATUS_BLOCK | ||
201 | #define DMA_HANDLER_REASON_TRANSFER_COMPLETE dmacHw_INTERRUPT_STATUS_TRANS | ||
202 | #define DMA_HANDLER_REASON_ERROR dmacHw_INTERRUPT_STATUS_ERROR | ||
203 | |||
204 | typedef void (*DMA_DeviceHandler_t) (DMA_Device_t dev, int reason, | ||
205 | void *userData); | ||
206 | |||
207 | #define DMA_DEVICE_FLAG_ON_DMA0 0x00000001 | ||
208 | #define DMA_DEVICE_FLAG_ON_DMA1 0x00000002 | ||
209 | #define DMA_DEVICE_FLAG_PORT_PER_DMAC 0x00000004 /* If set, it means that the port used on DMAC0 is different from the port used on DMAC1 */ | ||
210 | #define DMA_DEVICE_FLAG_ALLOC_DMA1_FIRST 0x00000008 /* If set, allocate from DMA1 before allocating from DMA0 */ | ||
211 | #define DMA_DEVICE_FLAG_IS_DEDICATED 0x00000100 | ||
212 | #define DMA_DEVICE_FLAG_NO_ISR 0x00000200 | ||
213 | #define DMA_DEVICE_FLAG_ALLOW_LARGE_FIFO 0x00000400 | ||
214 | #define DMA_DEVICE_FLAG_IN_USE 0x00000800 /* If set, device is in use on a channel */ | ||
215 | |||
216 | /* Note: Some DMA devices can be used from multiple DMA Controllers. The bitmask is used to */ | ||
217 | /* determine which DMA controllers a given device can be used from, and the interface */ | ||
218 | /* array determeines the actual interface number to use for a given controller. */ | ||
219 | |||
220 | typedef struct { | ||
221 | uint32_t flags; /* Bitmask of DMA_DEVICE_FLAG_xxx constants */ | ||
222 | uint8_t dedicatedController; /* Controller number to use if DMA_DEVICE_FLAG_IS_DEDICATED is set. */ | ||
223 | uint8_t dedicatedChannel; /* Channel number to use if DMA_DEVICE_FLAG_IS_DEDICATED is set. */ | ||
224 | const char *name; /* Will show up in the /proc entry */ | ||
225 | |||
226 | uint32_t dmacPort[DMA_NUM_CONTROLLERS]; /* Specifies the port number when DMA_DEVICE_FLAG_PORT_PER_DMAC flag is set */ | ||
227 | |||
228 | dmacHw_CONFIG_t config; /* Configuration to use when DMA'ing using this device */ | ||
229 | |||
230 | void *userData; /* Passed to the devHandler */ | ||
231 | DMA_DeviceHandler_t devHandler; /* Called when DMA operations finish. */ | ||
232 | |||
233 | timer_tick_count_t transferStartTime; /* Time the current transfer was started */ | ||
234 | |||
235 | /* The following statistical information will be collected and presented in a proc entry. */ | ||
236 | /* Note: With a contiuous bandwidth of 1 Gb/sec, it would take 584 years to overflow */ | ||
237 | /* a 64 bit counter. */ | ||
238 | |||
239 | uint64_t numTransfers; /* Number of DMA transfers performed */ | ||
240 | uint64_t transferTicks; /* Total time spent doing DMA transfers (measured in timer_tick_count_t's) */ | ||
241 | uint64_t transferBytes; /* Total bytes transferred */ | ||
242 | uint32_t timesBlocked; /* Number of times a channel was unavailable */ | ||
243 | uint32_t numBytes; /* Last transfer size */ | ||
244 | |||
245 | /* It's not possible to free memory which is allocated for the descriptors from within */ | ||
246 | /* the ISR. So make the presumption that a given device will tend to use the */ | ||
247 | /* same sized buffers over and over again, and we keep them around. */ | ||
248 | |||
249 | DMA_DescriptorRing_t ring; /* Ring of descriptors allocated for this device */ | ||
250 | |||
251 | /* We stash away some of the information from the previous transfer. If back-to-back */ | ||
252 | /* transfers are performed from the same buffer, then we don't have to keep re-initializing */ | ||
253 | /* the descriptor buffers. */ | ||
254 | |||
255 | uint32_t prevNumBytes; | ||
256 | dma_addr_t prevSrcData; | ||
257 | dma_addr_t prevDstData; | ||
258 | |||
259 | } DMA_DeviceAttribute_t; | ||
260 | |||
261 | /**************************************************************************** | ||
262 | * | ||
263 | * DMA_Channel_t, DMA_Controller_t, and DMA_State_t are really internal | ||
264 | * data structures and don't belong in this header file, but are included | ||
265 | * merely for discussion. | ||
266 | * | ||
267 | * By the time this is implemented, these structures will be moved out into | ||
268 | * the appropriate C source file instead. | ||
269 | * | ||
270 | *****************************************************************************/ | ||
271 | |||
272 | /**************************************************************************** | ||
273 | * | ||
274 | * The DMA_Channel_t contains state information about each DMA channel. Some | ||
275 | * of the channels are dedicated. Non-dedicated channels are shared | ||
276 | * amongst the other devices. | ||
277 | * | ||
278 | *****************************************************************************/ | ||
279 | |||
280 | #define DMA_CHANNEL_FLAG_IN_USE 0x00000001 | ||
281 | #define DMA_CHANNEL_FLAG_IS_DEDICATED 0x00000002 | ||
282 | #define DMA_CHANNEL_FLAG_NO_ISR 0x00000004 | ||
283 | #define DMA_CHANNEL_FLAG_LARGE_FIFO 0x00000008 | ||
284 | |||
285 | typedef struct { | ||
286 | uint32_t flags; /* bitmask of DMA_CHANNEL_FLAG_xxx constants */ | ||
287 | DMA_Device_t devType; /* Device this channel is currently reserved for */ | ||
288 | DMA_Device_t lastDevType; /* Device type that used this previously */ | ||
289 | char name[20]; /* Name passed onto request_irq */ | ||
290 | |||
291 | #if (DMA_DEBUG_TRACK_RESERVATION) | ||
292 | const char *fileName; /* Place where channel reservation took place */ | ||
293 | int lineNum; /* Place where channel reservation took place */ | ||
294 | #endif | ||
295 | dmacHw_HANDLE_t dmacHwHandle; /* low level channel handle. */ | ||
296 | |||
297 | } DMA_Channel_t; | ||
298 | |||
299 | /**************************************************************************** | ||
300 | * | ||
301 | * The DMA_Controller_t contains state information about each DMA controller. | ||
302 | * | ||
303 | * The freeChannelQ is stored in the controller data structure rather than | ||
304 | * the channel data structure since several of the devices are accessible | ||
305 | * from multiple controllers, and there is no way to know which controller | ||
306 | * will become available first. | ||
307 | * | ||
308 | *****************************************************************************/ | ||
309 | |||
310 | typedef struct { | ||
311 | DMA_Channel_t channel[DMA_NUM_CHANNELS]; | ||
312 | |||
313 | } DMA_Controller_t; | ||
314 | |||
315 | /**************************************************************************** | ||
316 | * | ||
317 | * The DMA_Global_t contains all of the global state information used by | ||
318 | * the DMA code. | ||
319 | * | ||
320 | * Callers which need to allocate a shared channel will be queued up | ||
321 | * on the freeChannelQ until a channel becomes available. | ||
322 | * | ||
323 | *****************************************************************************/ | ||
324 | |||
325 | typedef struct { | ||
326 | struct semaphore lock; /* acquired when manipulating table entries */ | ||
327 | wait_queue_head_t freeChannelQ; | ||
328 | |||
329 | DMA_Controller_t controller[DMA_NUM_CONTROLLERS]; | ||
330 | |||
331 | } DMA_Global_t; | ||
332 | |||
333 | /* ---- Variable Externs ------------------------------------------------- */ | ||
334 | |||
335 | extern DMA_DeviceAttribute_t DMA_gDeviceAttribute[DMA_NUM_DEVICE_ENTRIES]; | ||
336 | |||
337 | /* ---- Function Prototypes ---------------------------------------------- */ | ||
338 | |||
339 | #if defined(__KERNEL__) | ||
340 | |||
341 | /****************************************************************************/ | ||
342 | /** | ||
343 | * Initializes the DMA module. | ||
344 | * | ||
345 | * @return | ||
346 | * 0 - Success | ||
347 | * < 0 - Error | ||
348 | */ | ||
349 | /****************************************************************************/ | ||
350 | |||
351 | int dma_init(void); | ||
352 | |||
353 | #if (DMA_DEBUG_TRACK_RESERVATION) | ||
354 | DMA_Handle_t dma_request_channel_dbg(DMA_Device_t dev, const char *fileName, | ||
355 | int lineNum); | ||
356 | #define dma_request_channel(dev) dma_request_channel_dbg(dev, __FILE__, __LINE__) | ||
357 | #else | ||
358 | |||
359 | /****************************************************************************/ | ||
360 | /** | ||
361 | * Reserves a channel for use with @a dev. If the device is setup to use | ||
362 | * a shared channel, then this function will block until a free channel | ||
363 | * becomes available. | ||
364 | * | ||
365 | * @return | ||
366 | * >= 0 - A valid DMA Handle. | ||
367 | * -EBUSY - Device is currently being used. | ||
368 | * -ENODEV - Device handed in is invalid. | ||
369 | */ | ||
370 | /****************************************************************************/ | ||
371 | |||
372 | DMA_Handle_t dma_request_channel(DMA_Device_t dev /* Device to use with the allocated channel. */ | ||
373 | ); | ||
374 | #endif | ||
375 | |||
376 | /****************************************************************************/ | ||
377 | /** | ||
378 | * Frees a previously allocated DMA Handle. | ||
379 | * | ||
380 | * @return | ||
381 | * 0 - DMA Handle was released successfully. | ||
382 | * -EINVAL - Invalid DMA handle | ||
383 | */ | ||
384 | /****************************************************************************/ | ||
385 | |||
386 | int dma_free_channel(DMA_Handle_t channel /* DMA handle. */ | ||
387 | ); | ||
388 | |||
389 | /****************************************************************************/ | ||
390 | /** | ||
391 | * Determines if a given device has been configured as using a shared | ||
392 | * channel. | ||
393 | * | ||
394 | * @return boolean | ||
395 | * 0 Device uses a dedicated channel | ||
396 | * non-zero Device uses a shared channel | ||
397 | */ | ||
398 | /****************************************************************************/ | ||
399 | |||
400 | int dma_device_is_channel_shared(DMA_Device_t dev /* Device to check. */ | ||
401 | ); | ||
402 | |||
403 | /****************************************************************************/ | ||
404 | /** | ||
405 | * Allocates memory to hold a descriptor ring. The descriptor ring then | ||
406 | * needs to be populated by making one or more calls to | ||
407 | * dna_add_descriptors. | ||
408 | * | ||
409 | * The returned descriptor ring will be automatically initialized. | ||
410 | * | ||
411 | * @return | ||
412 | * 0 Descriptor ring was allocated successfully | ||
413 | * -ENOMEM Unable to allocate memory for the desired number of descriptors. | ||
414 | */ | ||
415 | /****************************************************************************/ | ||
416 | |||
417 | int dma_alloc_descriptor_ring(DMA_DescriptorRing_t *ring, /* Descriptor ring to populate */ | ||
418 | int numDescriptors /* Number of descriptors that need to be allocated. */ | ||
419 | ); | ||
420 | |||
421 | /****************************************************************************/ | ||
422 | /** | ||
423 | * Releases the memory which was previously allocated for a descriptor ring. | ||
424 | */ | ||
425 | /****************************************************************************/ | ||
426 | |||
427 | void dma_free_descriptor_ring(DMA_DescriptorRing_t *ring /* Descriptor to release */ | ||
428 | ); | ||
429 | |||
430 | /****************************************************************************/ | ||
431 | /** | ||
432 | * Initializes a descriptor ring, so that descriptors can be added to it. | ||
433 | * Once a descriptor ring has been allocated, it may be reinitialized for | ||
434 | * use with additional/different regions of memory. | ||
435 | * | ||
436 | * Note that if 7 descriptors are allocated, it's perfectly acceptable to | ||
437 | * initialize the ring with a smaller number of descriptors. The amount | ||
438 | * of memory allocated for the descriptor ring will not be reduced, and | ||
439 | * the descriptor ring may be reinitialized later | ||
440 | * | ||
441 | * @return | ||
442 | * 0 Descriptor ring was initialized successfully | ||
443 | * -ENOMEM The descriptor which was passed in has insufficient space | ||
444 | * to hold the desired number of descriptors. | ||
445 | */ | ||
446 | /****************************************************************************/ | ||
447 | |||
448 | int dma_init_descriptor_ring(DMA_DescriptorRing_t *ring, /* Descriptor ring to initialize */ | ||
449 | int numDescriptors /* Number of descriptors to initialize. */ | ||
450 | ); | ||
451 | |||
452 | /****************************************************************************/ | ||
453 | /** | ||
454 | * Determines the number of descriptors which would be required for a | ||
455 | * transfer of the indicated memory region. | ||
456 | * | ||
457 | * This function also needs to know which DMA device this transfer will | ||
458 | * be destined for, so that the appropriate DMA configuration can be retrieved. | ||
459 | * DMA parameters such as transfer width, and whether this is a memory-to-memory | ||
460 | * or memory-to-peripheral, etc can all affect the actual number of descriptors | ||
461 | * required. | ||
462 | * | ||
463 | * @return | ||
464 | * > 0 Returns the number of descriptors required for the indicated transfer | ||
465 | * -EINVAL Invalid device type for this kind of transfer | ||
466 | * (i.e. the device is _MEM_TO_DEV and not _DEV_TO_MEM) | ||
467 | * -ENOMEM Memory exhausted | ||
468 | */ | ||
469 | /****************************************************************************/ | ||
470 | |||
471 | int dma_calculate_descriptor_count(DMA_Device_t device, /* DMA Device that this will be associated with */ | ||
472 | dma_addr_t srcData, /* Place to get data to write to device */ | ||
473 | dma_addr_t dstData, /* Pointer to device data address */ | ||
474 | size_t numBytes /* Number of bytes to transfer to the device */ | ||
475 | ); | ||
476 | |||
477 | /****************************************************************************/ | ||
478 | /** | ||
479 | * Adds a region of memory to the descriptor ring. Note that it may take | ||
480 | * multiple descriptors for each region of memory. It is the callers | ||
481 | * responsibility to allocate a sufficiently large descriptor ring. | ||
482 | * | ||
483 | * @return | ||
484 | * 0 Descriptors were added successfully | ||
485 | * -EINVAL Invalid device type for this kind of transfer | ||
486 | * (i.e. the device is _MEM_TO_DEV and not _DEV_TO_MEM) | ||
487 | * -ENOMEM Memory exhausted | ||
488 | */ | ||
489 | /****************************************************************************/ | ||
490 | |||
491 | int dma_add_descriptors(DMA_DescriptorRing_t *ring, /* Descriptor ring to add descriptors to */ | ||
492 | DMA_Device_t device, /* DMA Device that descriptors are for */ | ||
493 | dma_addr_t srcData, /* Place to get data (memory or device) */ | ||
494 | dma_addr_t dstData, /* Place to put data (memory or device) */ | ||
495 | size_t numBytes /* Number of bytes to transfer to the device */ | ||
496 | ); | ||
497 | |||
498 | /****************************************************************************/ | ||
499 | /** | ||
500 | * Sets the descriptor ring associated with a device. | ||
501 | * | ||
502 | * Once set, the descriptor ring will be associated with the device, even | ||
503 | * across channel request/free calls. Passing in a NULL descriptor ring | ||
504 | * will release any descriptor ring currently associated with the device. | ||
505 | * | ||
506 | * Note: If you call dma_transfer, or one of the other dma_alloc_ functions | ||
507 | * the descriptor ring may be released and reallocated. | ||
508 | * | ||
509 | * Note: This function will release the descriptor memory for any current | ||
510 | * descriptor ring associated with this device. | ||
511 | */ | ||
512 | /****************************************************************************/ | ||
513 | |||
514 | int dma_set_device_descriptor_ring(DMA_Device_t device, /* Device to update the descriptor ring for. */ | ||
515 | DMA_DescriptorRing_t *ring /* Descriptor ring to add descriptors to */ | ||
516 | ); | ||
517 | |||
518 | /****************************************************************************/ | ||
519 | /** | ||
520 | * Retrieves the descriptor ring associated with a device. | ||
521 | */ | ||
522 | /****************************************************************************/ | ||
523 | |||
524 | int dma_get_device_descriptor_ring(DMA_Device_t device, /* Device to retrieve the descriptor ring for. */ | ||
525 | DMA_DescriptorRing_t *ring /* Place to store retrieved ring */ | ||
526 | ); | ||
527 | |||
528 | /****************************************************************************/ | ||
529 | /** | ||
530 | * Allocates buffers for the descriptors. This is normally done automatically | ||
531 | * but needs to be done explicitly when initiating a dma from interrupt | ||
532 | * context. | ||
533 | * | ||
534 | * @return | ||
535 | * 0 Descriptors were allocated successfully | ||
536 | * -EINVAL Invalid device type for this kind of transfer | ||
537 | * (i.e. the device is _MEM_TO_DEV and not _DEV_TO_MEM) | ||
538 | * -ENOMEM Memory exhausted | ||
539 | */ | ||
540 | /****************************************************************************/ | ||
541 | |||
542 | int dma_alloc_descriptors(DMA_Handle_t handle, /* DMA Handle */ | ||
543 | dmacHw_TRANSFER_TYPE_e transferType, /* Type of transfer being performed */ | ||
544 | dma_addr_t srcData, /* Place to get data to write to device */ | ||
545 | dma_addr_t dstData, /* Pointer to device data address */ | ||
546 | size_t numBytes /* Number of bytes to transfer to the device */ | ||
547 | ); | ||
548 | |||
549 | /****************************************************************************/ | ||
550 | /** | ||
551 | * Allocates and sets up descriptors for a double buffered circular buffer. | ||
552 | * | ||
553 | * This is primarily intended to be used for things like the ingress samples | ||
554 | * from a microphone. | ||
555 | * | ||
556 | * @return | ||
557 | * > 0 Number of descriptors actually allocated. | ||
558 | * -EINVAL Invalid device type for this kind of transfer | ||
559 | * (i.e. the device is _MEM_TO_DEV and not _DEV_TO_MEM) | ||
560 | * -ENOMEM Memory exhausted | ||
561 | */ | ||
562 | /****************************************************************************/ | ||
563 | |||
564 | int dma_alloc_double_dst_descriptors(DMA_Handle_t handle, /* DMA Handle */ | ||
565 | dma_addr_t srcData, /* Physical address of source data */ | ||
566 | dma_addr_t dstData1, /* Physical address of first destination buffer */ | ||
567 | dma_addr_t dstData2, /* Physical address of second destination buffer */ | ||
568 | size_t numBytes /* Number of bytes in each destination buffer */ | ||
569 | ); | ||
570 | |||
571 | /****************************************************************************/ | ||
572 | /** | ||
573 | * Initializes a DMA_MemMap_t data structure | ||
574 | */ | ||
575 | /****************************************************************************/ | ||
576 | |||
577 | int dma_init_mem_map(DMA_MemMap_t *memMap /* Stores state information about the map */ | ||
578 | ); | ||
579 | |||
580 | /****************************************************************************/ | ||
581 | /** | ||
582 | * Releases any memory currently being held by a memory mapping structure. | ||
583 | */ | ||
584 | /****************************************************************************/ | ||
585 | |||
586 | int dma_term_mem_map(DMA_MemMap_t *memMap /* Stores state information about the map */ | ||
587 | ); | ||
588 | |||
589 | /****************************************************************************/ | ||
590 | /** | ||
591 | * Looks at a memory address and categorizes it. | ||
592 | * | ||
593 | * @return One of the values from the DMA_MemType_t enumeration. | ||
594 | */ | ||
595 | /****************************************************************************/ | ||
596 | |||
597 | DMA_MemType_t dma_mem_type(void *addr); | ||
598 | |||
599 | /****************************************************************************/ | ||
600 | /** | ||
601 | * Sets the process (aka userTask) associated with a mem map. This is | ||
602 | * required if user-mode segments will be added to the mapping. | ||
603 | */ | ||
604 | /****************************************************************************/ | ||
605 | |||
606 | static inline void dma_mem_map_set_user_task(DMA_MemMap_t *memMap, | ||
607 | struct task_struct *task) | ||
608 | { | ||
609 | memMap->userTask = task; | ||
610 | } | ||
611 | |||
612 | /****************************************************************************/ | ||
613 | /** | ||
614 | * Looks at a memory address and determines if we support DMA'ing to/from | ||
615 | * that type of memory. | ||
616 | * | ||
617 | * @return boolean - | ||
618 | * return value != 0 means dma supported | ||
619 | * return value == 0 means dma not supported | ||
620 | */ | ||
621 | /****************************************************************************/ | ||
622 | |||
623 | int dma_mem_supports_dma(void *addr); | ||
624 | |||
625 | /****************************************************************************/ | ||
626 | /** | ||
627 | * Initializes a memory map for use. Since this function acquires a | ||
628 | * sempaphore within the memory map, it is VERY important that dma_unmap | ||
629 | * be called when you're finished using the map. | ||
630 | */ | ||
631 | /****************************************************************************/ | ||
632 | |||
633 | int dma_map_start(DMA_MemMap_t *memMap, /* Stores state information about the map */ | ||
634 | enum dma_data_direction dir /* Direction that the mapping will be going */ | ||
635 | ); | ||
636 | |||
637 | /****************************************************************************/ | ||
638 | /** | ||
639 | * Adds a segment of memory to a memory map. | ||
640 | * | ||
641 | * @return 0 on success, error code otherwise. | ||
642 | */ | ||
643 | /****************************************************************************/ | ||
644 | |||
645 | int dma_map_add_region(DMA_MemMap_t *memMap, /* Stores state information about the map */ | ||
646 | void *mem, /* Virtual address that we want to get a map of */ | ||
647 | size_t numBytes /* Number of bytes being mapped */ | ||
648 | ); | ||
649 | |||
650 | /****************************************************************************/ | ||
651 | /** | ||
652 | * Creates a descriptor ring from a memory mapping. | ||
653 | * | ||
654 | * @return 0 on sucess, error code otherwise. | ||
655 | */ | ||
656 | /****************************************************************************/ | ||
657 | |||
658 | int dma_map_create_descriptor_ring(DMA_Device_t dev, /* DMA device (where the ring is stored) */ | ||
659 | DMA_MemMap_t *memMap, /* Memory map that will be used */ | ||
660 | dma_addr_t devPhysAddr /* Physical address of device */ | ||
661 | ); | ||
662 | |||
663 | /****************************************************************************/ | ||
664 | /** | ||
665 | * Maps in a memory region such that it can be used for performing a DMA. | ||
666 | * | ||
667 | * @return | ||
668 | */ | ||
669 | /****************************************************************************/ | ||
670 | |||
671 | int dma_map_mem(DMA_MemMap_t *memMap, /* Stores state information about the map */ | ||
672 | void *addr, /* Virtual address that we want to get a map of */ | ||
673 | size_t count, /* Number of bytes being mapped */ | ||
674 | enum dma_data_direction dir /* Direction that the mapping will be going */ | ||
675 | ); | ||
676 | |||
677 | /****************************************************************************/ | ||
678 | /** | ||
679 | * Maps in a memory region such that it can be used for performing a DMA. | ||
680 | * | ||
681 | * @return | ||
682 | */ | ||
683 | /****************************************************************************/ | ||
684 | |||
685 | int dma_unmap(DMA_MemMap_t *memMap, /* Stores state information about the map */ | ||
686 | int dirtied /* non-zero if any of the pages were modified */ | ||
687 | ); | ||
688 | |||
689 | /****************************************************************************/ | ||
690 | /** | ||
691 | * Initiates a transfer when the descriptors have already been setup. | ||
692 | * | ||
693 | * This is a special case, and normally, the dma_transfer_xxx functions should | ||
694 | * be used. | ||
695 | * | ||
696 | * @return | ||
697 | * 0 Transfer was started successfully | ||
698 | * -ENODEV Invalid handle | ||
699 | */ | ||
700 | /****************************************************************************/ | ||
701 | |||
702 | int dma_start_transfer(DMA_Handle_t handle); | ||
703 | |||
704 | /****************************************************************************/ | ||
705 | /** | ||
706 | * Stops a previously started DMA transfer. | ||
707 | * | ||
708 | * @return | ||
709 | * 0 Transfer was stopped successfully | ||
710 | * -ENODEV Invalid handle | ||
711 | */ | ||
712 | /****************************************************************************/ | ||
713 | |||
714 | int dma_stop_transfer(DMA_Handle_t handle); | ||
715 | |||
716 | /****************************************************************************/ | ||
717 | /** | ||
718 | * Waits for a DMA to complete by polling. This function is only intended | ||
719 | * to be used for testing. Interrupts should be used for most DMA operations. | ||
720 | */ | ||
721 | /****************************************************************************/ | ||
722 | |||
723 | int dma_wait_transfer_done(DMA_Handle_t handle); | ||
724 | |||
725 | /****************************************************************************/ | ||
726 | /** | ||
727 | * Initiates a DMA transfer | ||
728 | * | ||
729 | * @return | ||
730 | * 0 Transfer was started successfully | ||
731 | * -EINVAL Invalid device type for this kind of transfer | ||
732 | * (i.e. the device is _MEM_TO_DEV and not _DEV_TO_MEM) | ||
733 | */ | ||
734 | /****************************************************************************/ | ||
735 | |||
736 | int dma_transfer(DMA_Handle_t handle, /* DMA Handle */ | ||
737 | dmacHw_TRANSFER_TYPE_e transferType, /* Type of transfer being performed */ | ||
738 | dma_addr_t srcData, /* Place to get data to write to device */ | ||
739 | dma_addr_t dstData, /* Pointer to device data address */ | ||
740 | size_t numBytes /* Number of bytes to transfer to the device */ | ||
741 | ); | ||
742 | |||
743 | /****************************************************************************/ | ||
744 | /** | ||
745 | * Initiates a transfer from memory to a device. | ||
746 | * | ||
747 | * @return | ||
748 | * 0 Transfer was started successfully | ||
749 | * -EINVAL Invalid device type for this kind of transfer | ||
750 | * (i.e. the device is _DEV_TO_MEM and not _MEM_TO_DEV) | ||
751 | */ | ||
752 | /****************************************************************************/ | ||
753 | |||
754 | static inline int dma_transfer_to_device(DMA_Handle_t handle, /* DMA Handle */ | ||
755 | dma_addr_t srcData, /* Place to get data to write to device (physical address) */ | ||
756 | dma_addr_t dstData, /* Pointer to device data address (physical address) */ | ||
757 | size_t numBytes /* Number of bytes to transfer to the device */ | ||
758 | ) { | ||
759 | return dma_transfer(handle, | ||
760 | dmacHw_TRANSFER_TYPE_MEM_TO_PERIPHERAL, | ||
761 | srcData, dstData, numBytes); | ||
762 | } | ||
763 | |||
764 | /****************************************************************************/ | ||
765 | /** | ||
766 | * Initiates a transfer from a device to memory. | ||
767 | * | ||
768 | * @return | ||
769 | * 0 Transfer was started successfully | ||
770 | * -EINVAL Invalid device type for this kind of transfer | ||
771 | * (i.e. the device is _MEM_TO_DEV and not _DEV_TO_MEM) | ||
772 | */ | ||
773 | /****************************************************************************/ | ||
774 | |||
775 | static inline int dma_transfer_from_device(DMA_Handle_t handle, /* DMA Handle */ | ||
776 | dma_addr_t srcData, /* Pointer to the device data address (physical address) */ | ||
777 | dma_addr_t dstData, /* Place to store data retrieved from the device (physical address) */ | ||
778 | size_t numBytes /* Number of bytes to retrieve from the device */ | ||
779 | ) { | ||
780 | return dma_transfer(handle, | ||
781 | dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM, | ||
782 | srcData, dstData, numBytes); | ||
783 | } | ||
784 | |||
785 | /****************************************************************************/ | ||
786 | /** | ||
787 | * Initiates a memory to memory transfer. | ||
788 | * | ||
789 | * @return | ||
790 | * 0 Transfer was started successfully | ||
791 | * -EINVAL Invalid device type for this kind of transfer | ||
792 | * (i.e. the device wasn't DMA_DEVICE_MEM_TO_MEM) | ||
793 | */ | ||
794 | /****************************************************************************/ | ||
795 | |||
796 | static inline int dma_transfer_mem_to_mem(DMA_Handle_t handle, /* DMA Handle */ | ||
797 | dma_addr_t srcData, /* Place to transfer data from (physical address) */ | ||
798 | dma_addr_t dstData, /* Place to transfer data to (physical address) */ | ||
799 | size_t numBytes /* Number of bytes to transfer */ | ||
800 | ) { | ||
801 | return dma_transfer(handle, | ||
802 | dmacHw_TRANSFER_TYPE_MEM_TO_MEM, | ||
803 | srcData, dstData, numBytes); | ||
804 | } | ||
805 | |||
806 | /****************************************************************************/ | ||
807 | /** | ||
808 | * Set the callback function which will be called when a transfer completes. | ||
809 | * If a NULL callback function is set, then no callback will occur. | ||
810 | * | ||
811 | * @note @a devHandler will be called from IRQ context. | ||
812 | * | ||
813 | * @return | ||
814 | * 0 - Success | ||
815 | * -ENODEV - Device handed in is invalid. | ||
816 | */ | ||
817 | /****************************************************************************/ | ||
818 | |||
819 | int dma_set_device_handler(DMA_Device_t dev, /* Device to set the callback for. */ | ||
820 | DMA_DeviceHandler_t devHandler, /* Function to call when the DMA completes */ | ||
821 | void *userData /* Pointer which will be passed to devHandler. */ | ||
822 | ); | ||
823 | |||
824 | #endif | ||
825 | |||
826 | #endif /* ASM_ARM_ARCH_BCMRING_DMA_H */ | ||