Commit | Line | Data |
---|---|---|
7c4c2951 LC |
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 | * | |
af901ca1 | 654 | * @return 0 on success, error code otherwise. |
7c4c2951 LC |
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 */ |