1 /*****************************************************************************
2 * Copyright 2004 - 2008 Broadcom Corporation. All rights reserved.
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").
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
13 *****************************************************************************/
15 /****************************************************************************/
19 * @brief API definitions for the linux DMA interface.
21 /****************************************************************************/
23 #if !defined(ASM_ARM_ARCH_BCMRING_DMA_H)
24 #define ASM_ARM_ARCH_BCMRING_DMA_H
26 /* ---- Include Files ---------------------------------------------------- */
28 #include <linux/kernel.h>
29 #include <linux/semaphore.h>
30 #include <csp/dmacHw.h>
31 #include <mach/timer.h>
33 /* ---- Constants and Types ---------------------------------------------- */
35 /* If DMA_DEBUG_TRACK_RESERVATION is set to a non-zero value, then the filename */
36 /* and line number of the reservation request will be recorded in the channel table */
38 #define DMA_DEBUG_TRACK_RESERVATION 1
40 #define DMA_NUM_CONTROLLERS 2
41 #define DMA_NUM_CHANNELS 8 /* per controller */
44 DMA_DEVICE_MEM_TO_MEM
, /* For memory to memory transfers */
45 DMA_DEVICE_I2S0_DEV_TO_MEM
,
46 DMA_DEVICE_I2S0_MEM_TO_DEV
,
47 DMA_DEVICE_I2S1_DEV_TO_MEM
,
48 DMA_DEVICE_I2S1_MEM_TO_DEV
,
49 DMA_DEVICE_APM_CODEC_A_DEV_TO_MEM
,
50 DMA_DEVICE_APM_CODEC_A_MEM_TO_DEV
,
51 DMA_DEVICE_APM_CODEC_B_DEV_TO_MEM
,
52 DMA_DEVICE_APM_CODEC_B_MEM_TO_DEV
,
53 DMA_DEVICE_APM_CODEC_C_DEV_TO_MEM
, /* Additional mic input for beam-forming */
54 DMA_DEVICE_APM_PCM0_DEV_TO_MEM
,
55 DMA_DEVICE_APM_PCM0_MEM_TO_DEV
,
56 DMA_DEVICE_APM_PCM1_DEV_TO_MEM
,
57 DMA_DEVICE_APM_PCM1_MEM_TO_DEV
,
58 DMA_DEVICE_SPUM_DEV_TO_MEM
,
59 DMA_DEVICE_SPUM_MEM_TO_DEV
,
60 DMA_DEVICE_SPIH_DEV_TO_MEM
,
61 DMA_DEVICE_SPIH_MEM_TO_DEV
,
62 DMA_DEVICE_UART_A_DEV_TO_MEM
,
63 DMA_DEVICE_UART_A_MEM_TO_DEV
,
64 DMA_DEVICE_UART_B_DEV_TO_MEM
,
65 DMA_DEVICE_UART_B_MEM_TO_DEV
,
66 DMA_DEVICE_PIF_MEM_TO_DEV
,
67 DMA_DEVICE_PIF_DEV_TO_MEM
,
68 DMA_DEVICE_ESW_DEV_TO_MEM
,
69 DMA_DEVICE_ESW_MEM_TO_DEV
,
70 DMA_DEVICE_VPM_MEM_TO_MEM
,
71 DMA_DEVICE_CLCD_MEM_TO_MEM
,
72 DMA_DEVICE_NAND_MEM_TO_MEM
,
73 DMA_DEVICE_MEM_TO_VRAM
,
74 DMA_DEVICE_VRAM_TO_MEM
,
76 /* Add new entries before this line. */
78 DMA_NUM_DEVICE_ENTRIES
,
79 DMA_DEVICE_NONE
= 0xff, /* Special value to indicate that no device is currently assigned. */
83 /****************************************************************************
85 * The DMA_Handle_t is the primary object used by callers of the API.
87 *****************************************************************************/
89 #define DMA_INVALID_HANDLE ((DMA_Handle_t) -1)
91 typedef int DMA_Handle_t
;
93 /****************************************************************************
95 * The DMA_DescriptorRing_t contains a ring of descriptors which is used
96 * to point to regions of memory.
98 *****************************************************************************/
101 void *virtAddr
; /* Virtual Address of the descriptor ring */
102 dma_addr_t physAddr
; /* Physical address of the descriptor ring */
103 int descriptorsAllocated
; /* Number of descriptors allocated in the descriptor ring */
104 size_t bytesAllocated
; /* Number of bytes allocated in the descriptor ring */
106 } DMA_DescriptorRing_t
;
108 /****************************************************************************
110 * The DMA_DeviceAttribute_t contains information which describes a
111 * particular DMA device (or peripheral).
113 * It is anticipated that the arrary of DMA_DeviceAttribute_t's will be
114 * statically initialized.
116 *****************************************************************************/
118 /* The device handler is called whenever a DMA operation completes. The reaon */
119 /* for it to be called will be a bitmask with one or more of the following bits */
122 #define DMA_HANDLER_REASON_BLOCK_COMPLETE dmacHw_INTERRUPT_STATUS_BLOCK
123 #define DMA_HANDLER_REASON_TRANSFER_COMPLETE dmacHw_INTERRUPT_STATUS_TRANS
124 #define DMA_HANDLER_REASON_ERROR dmacHw_INTERRUPT_STATUS_ERROR
126 typedef void (*DMA_DeviceHandler_t
) (DMA_Device_t dev
, int reason
,
129 #define DMA_DEVICE_FLAG_ON_DMA0 0x00000001
130 #define DMA_DEVICE_FLAG_ON_DMA1 0x00000002
131 #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 */
132 #define DMA_DEVICE_FLAG_ALLOC_DMA1_FIRST 0x00000008 /* If set, allocate from DMA1 before allocating from DMA0 */
133 #define DMA_DEVICE_FLAG_IS_DEDICATED 0x00000100
134 #define DMA_DEVICE_FLAG_NO_ISR 0x00000200
135 #define DMA_DEVICE_FLAG_ALLOW_LARGE_FIFO 0x00000400
136 #define DMA_DEVICE_FLAG_IN_USE 0x00000800 /* If set, device is in use on a channel */
138 /* Note: Some DMA devices can be used from multiple DMA Controllers. The bitmask is used to */
139 /* determine which DMA controllers a given device can be used from, and the interface */
140 /* array determeines the actual interface number to use for a given controller. */
143 uint32_t flags
; /* Bitmask of DMA_DEVICE_FLAG_xxx constants */
144 uint8_t dedicatedController
; /* Controller number to use if DMA_DEVICE_FLAG_IS_DEDICATED is set. */
145 uint8_t dedicatedChannel
; /* Channel number to use if DMA_DEVICE_FLAG_IS_DEDICATED is set. */
146 const char *name
; /* Will show up in the /proc entry */
148 uint32_t dmacPort
[DMA_NUM_CONTROLLERS
]; /* Specifies the port number when DMA_DEVICE_FLAG_PORT_PER_DMAC flag is set */
150 dmacHw_CONFIG_t config
; /* Configuration to use when DMA'ing using this device */
152 void *userData
; /* Passed to the devHandler */
153 DMA_DeviceHandler_t devHandler
; /* Called when DMA operations finish. */
155 timer_tick_count_t transferStartTime
; /* Time the current transfer was started */
157 /* The following statistical information will be collected and presented in a proc entry. */
158 /* Note: With a contiuous bandwidth of 1 Gb/sec, it would take 584 years to overflow */
159 /* a 64 bit counter. */
161 uint64_t numTransfers
; /* Number of DMA transfers performed */
162 uint64_t transferTicks
; /* Total time spent doing DMA transfers (measured in timer_tick_count_t's) */
163 uint64_t transferBytes
; /* Total bytes transferred */
164 uint32_t timesBlocked
; /* Number of times a channel was unavailable */
165 uint32_t numBytes
; /* Last transfer size */
167 /* It's not possible to free memory which is allocated for the descriptors from within */
168 /* the ISR. So make the presumption that a given device will tend to use the */
169 /* same sized buffers over and over again, and we keep them around. */
171 DMA_DescriptorRing_t ring
; /* Ring of descriptors allocated for this device */
173 /* We stash away some of the information from the previous transfer. If back-to-back */
174 /* transfers are performed from the same buffer, then we don't have to keep re-initializing */
175 /* the descriptor buffers. */
177 uint32_t prevNumBytes
;
178 dma_addr_t prevSrcData
;
179 dma_addr_t prevDstData
;
181 } DMA_DeviceAttribute_t
;
183 /****************************************************************************
185 * DMA_Channel_t, DMA_Controller_t, and DMA_State_t are really internal
186 * data structures and don't belong in this header file, but are included
187 * merely for discussion.
189 * By the time this is implemented, these structures will be moved out into
190 * the appropriate C source file instead.
192 *****************************************************************************/
194 /****************************************************************************
196 * The DMA_Channel_t contains state information about each DMA channel. Some
197 * of the channels are dedicated. Non-dedicated channels are shared
198 * amongst the other devices.
200 *****************************************************************************/
202 #define DMA_CHANNEL_FLAG_IN_USE 0x00000001
203 #define DMA_CHANNEL_FLAG_IS_DEDICATED 0x00000002
204 #define DMA_CHANNEL_FLAG_NO_ISR 0x00000004
205 #define DMA_CHANNEL_FLAG_LARGE_FIFO 0x00000008
208 uint32_t flags
; /* bitmask of DMA_CHANNEL_FLAG_xxx constants */
209 DMA_Device_t devType
; /* Device this channel is currently reserved for */
210 DMA_Device_t lastDevType
; /* Device type that used this previously */
211 char name
[20]; /* Name passed onto request_irq */
213 #if (DMA_DEBUG_TRACK_RESERVATION)
214 const char *fileName
; /* Place where channel reservation took place */
215 int lineNum
; /* Place where channel reservation took place */
217 dmacHw_HANDLE_t dmacHwHandle
; /* low level channel handle. */
221 /****************************************************************************
223 * The DMA_Controller_t contains state information about each DMA controller.
225 * The freeChannelQ is stored in the controller data structure rather than
226 * the channel data structure since several of the devices are accessible
227 * from multiple controllers, and there is no way to know which controller
228 * will become available first.
230 *****************************************************************************/
233 DMA_Channel_t channel
[DMA_NUM_CHANNELS
];
237 /****************************************************************************
239 * The DMA_Global_t contains all of the global state information used by
242 * Callers which need to allocate a shared channel will be queued up
243 * on the freeChannelQ until a channel becomes available.
245 *****************************************************************************/
248 struct semaphore lock
; /* acquired when manipulating table entries */
249 wait_queue_head_t freeChannelQ
;
251 DMA_Controller_t controller
[DMA_NUM_CONTROLLERS
];
255 /* ---- Variable Externs ------------------------------------------------- */
257 extern DMA_DeviceAttribute_t DMA_gDeviceAttribute
[DMA_NUM_DEVICE_ENTRIES
];
259 /* ---- Function Prototypes ---------------------------------------------- */
261 #if defined(__KERNEL__)
263 /****************************************************************************/
265 * Initializes the DMA module.
271 /****************************************************************************/
275 #if (DMA_DEBUG_TRACK_RESERVATION)
276 DMA_Handle_t
dma_request_channel_dbg(DMA_Device_t dev
, const char *fileName
,
278 #define dma_request_channel(dev) dma_request_channel_dbg(dev, __FILE__, __LINE__)
281 /****************************************************************************/
283 * Reserves a channel for use with @a dev. If the device is setup to use
284 * a shared channel, then this function will block until a free channel
288 * >= 0 - A valid DMA Handle.
289 * -EBUSY - Device is currently being used.
290 * -ENODEV - Device handed in is invalid.
292 /****************************************************************************/
294 DMA_Handle_t
dma_request_channel(DMA_Device_t dev
/* Device to use with the allocated channel. */
298 /****************************************************************************/
300 * Frees a previously allocated DMA Handle.
303 * 0 - DMA Handle was released successfully.
304 * -EINVAL - Invalid DMA handle
306 /****************************************************************************/
308 int dma_free_channel(DMA_Handle_t channel
/* DMA handle. */
311 /****************************************************************************/
313 * Determines if a given device has been configured as using a shared
317 * 0 Device uses a dedicated channel
318 * non-zero Device uses a shared channel
320 /****************************************************************************/
322 int dma_device_is_channel_shared(DMA_Device_t dev
/* Device to check. */
325 /****************************************************************************/
327 * Allocates memory to hold a descriptor ring. The descriptor ring then
328 * needs to be populated by making one or more calls to
329 * dna_add_descriptors.
331 * The returned descriptor ring will be automatically initialized.
334 * 0 Descriptor ring was allocated successfully
335 * -ENOMEM Unable to allocate memory for the desired number of descriptors.
337 /****************************************************************************/
339 int dma_alloc_descriptor_ring(DMA_DescriptorRing_t
*ring
, /* Descriptor ring to populate */
340 int numDescriptors
/* Number of descriptors that need to be allocated. */
343 /****************************************************************************/
345 * Releases the memory which was previously allocated for a descriptor ring.
347 /****************************************************************************/
349 void dma_free_descriptor_ring(DMA_DescriptorRing_t
*ring
/* Descriptor to release */
352 /****************************************************************************/
354 * Initializes a descriptor ring, so that descriptors can be added to it.
355 * Once a descriptor ring has been allocated, it may be reinitialized for
356 * use with additional/different regions of memory.
358 * Note that if 7 descriptors are allocated, it's perfectly acceptable to
359 * initialize the ring with a smaller number of descriptors. The amount
360 * of memory allocated for the descriptor ring will not be reduced, and
361 * the descriptor ring may be reinitialized later
364 * 0 Descriptor ring was initialized successfully
365 * -ENOMEM The descriptor which was passed in has insufficient space
366 * to hold the desired number of descriptors.
368 /****************************************************************************/
370 int dma_init_descriptor_ring(DMA_DescriptorRing_t
*ring
, /* Descriptor ring to initialize */
371 int numDescriptors
/* Number of descriptors to initialize. */
374 /****************************************************************************/
376 * Determines the number of descriptors which would be required for a
377 * transfer of the indicated memory region.
379 * This function also needs to know which DMA device this transfer will
380 * be destined for, so that the appropriate DMA configuration can be retrieved.
381 * DMA parameters such as transfer width, and whether this is a memory-to-memory
382 * or memory-to-peripheral, etc can all affect the actual number of descriptors
386 * > 0 Returns the number of descriptors required for the indicated transfer
387 * -EINVAL Invalid device type for this kind of transfer
388 * (i.e. the device is _MEM_TO_DEV and not _DEV_TO_MEM)
389 * -ENOMEM Memory exhausted
391 /****************************************************************************/
393 int dma_calculate_descriptor_count(DMA_Device_t device
, /* DMA Device that this will be associated with */
394 dma_addr_t srcData
, /* Place to get data to write to device */
395 dma_addr_t dstData
, /* Pointer to device data address */
396 size_t numBytes
/* Number of bytes to transfer to the device */
399 /****************************************************************************/
401 * Adds a region of memory to the descriptor ring. Note that it may take
402 * multiple descriptors for each region of memory. It is the callers
403 * responsibility to allocate a sufficiently large descriptor ring.
406 * 0 Descriptors were added successfully
407 * -EINVAL Invalid device type for this kind of transfer
408 * (i.e. the device is _MEM_TO_DEV and not _DEV_TO_MEM)
409 * -ENOMEM Memory exhausted
411 /****************************************************************************/
413 int dma_add_descriptors(DMA_DescriptorRing_t
*ring
, /* Descriptor ring to add descriptors to */
414 DMA_Device_t device
, /* DMA Device that descriptors are for */
415 dma_addr_t srcData
, /* Place to get data (memory or device) */
416 dma_addr_t dstData
, /* Place to put data (memory or device) */
417 size_t numBytes
/* Number of bytes to transfer to the device */
420 /****************************************************************************/
422 * Sets the descriptor ring associated with a device.
424 * Once set, the descriptor ring will be associated with the device, even
425 * across channel request/free calls. Passing in a NULL descriptor ring
426 * will release any descriptor ring currently associated with the device.
428 * Note: If you call dma_transfer, or one of the other dma_alloc_ functions
429 * the descriptor ring may be released and reallocated.
431 * Note: This function will release the descriptor memory for any current
432 * descriptor ring associated with this device.
434 /****************************************************************************/
436 int dma_set_device_descriptor_ring(DMA_Device_t device
, /* Device to update the descriptor ring for. */
437 DMA_DescriptorRing_t
*ring
/* Descriptor ring to add descriptors to */
440 /****************************************************************************/
442 * Retrieves the descriptor ring associated with a device.
444 /****************************************************************************/
446 int dma_get_device_descriptor_ring(DMA_Device_t device
, /* Device to retrieve the descriptor ring for. */
447 DMA_DescriptorRing_t
*ring
/* Place to store retrieved ring */
450 /****************************************************************************/
452 * Allocates buffers for the descriptors. This is normally done automatically
453 * but needs to be done explicitly when initiating a dma from interrupt
457 * 0 Descriptors were allocated successfully
458 * -EINVAL Invalid device type for this kind of transfer
459 * (i.e. the device is _MEM_TO_DEV and not _DEV_TO_MEM)
460 * -ENOMEM Memory exhausted
462 /****************************************************************************/
464 int dma_alloc_descriptors(DMA_Handle_t handle
, /* DMA Handle */
465 dmacHw_TRANSFER_TYPE_e transferType
, /* Type of transfer being performed */
466 dma_addr_t srcData
, /* Place to get data to write to device */
467 dma_addr_t dstData
, /* Pointer to device data address */
468 size_t numBytes
/* Number of bytes to transfer to the device */
471 /****************************************************************************/
473 * Allocates and sets up descriptors for a double buffered circular buffer.
475 * This is primarily intended to be used for things like the ingress samples
479 * > 0 Number of descriptors actually allocated.
480 * -EINVAL Invalid device type for this kind of transfer
481 * (i.e. the device is _MEM_TO_DEV and not _DEV_TO_MEM)
482 * -ENOMEM Memory exhausted
484 /****************************************************************************/
486 int dma_alloc_double_dst_descriptors(DMA_Handle_t handle
, /* DMA Handle */
487 dma_addr_t srcData
, /* Physical address of source data */
488 dma_addr_t dstData1
, /* Physical address of first destination buffer */
489 dma_addr_t dstData2
, /* Physical address of second destination buffer */
490 size_t numBytes
/* Number of bytes in each destination buffer */
493 /****************************************************************************/
495 * Initiates a transfer when the descriptors have already been setup.
497 * This is a special case, and normally, the dma_transfer_xxx functions should
501 * 0 Transfer was started successfully
502 * -ENODEV Invalid handle
504 /****************************************************************************/
506 int dma_start_transfer(DMA_Handle_t handle
);
508 /****************************************************************************/
510 * Stops a previously started DMA transfer.
513 * 0 Transfer was stopped successfully
514 * -ENODEV Invalid handle
516 /****************************************************************************/
518 int dma_stop_transfer(DMA_Handle_t handle
);
520 /****************************************************************************/
522 * Waits for a DMA to complete by polling. This function is only intended
523 * to be used for testing. Interrupts should be used for most DMA operations.
525 /****************************************************************************/
527 int dma_wait_transfer_done(DMA_Handle_t handle
);
529 /****************************************************************************/
531 * Initiates a DMA transfer
534 * 0 Transfer was started successfully
535 * -EINVAL Invalid device type for this kind of transfer
536 * (i.e. the device is _MEM_TO_DEV and not _DEV_TO_MEM)
538 /****************************************************************************/
540 int dma_transfer(DMA_Handle_t handle
, /* DMA Handle */
541 dmacHw_TRANSFER_TYPE_e transferType
, /* Type of transfer being performed */
542 dma_addr_t srcData
, /* Place to get data to write to device */
543 dma_addr_t dstData
, /* Pointer to device data address */
544 size_t numBytes
/* Number of bytes to transfer to the device */
547 /****************************************************************************/
549 * Initiates a transfer from memory to a device.
552 * 0 Transfer was started successfully
553 * -EINVAL Invalid device type for this kind of transfer
554 * (i.e. the device is _DEV_TO_MEM and not _MEM_TO_DEV)
556 /****************************************************************************/
558 static inline int dma_transfer_to_device(DMA_Handle_t handle
, /* DMA Handle */
559 dma_addr_t srcData
, /* Place to get data to write to device (physical address) */
560 dma_addr_t dstData
, /* Pointer to device data address (physical address) */
561 size_t numBytes
/* Number of bytes to transfer to the device */
563 return dma_transfer(handle
,
564 dmacHw_TRANSFER_TYPE_MEM_TO_PERIPHERAL
,
565 srcData
, dstData
, numBytes
);
568 /****************************************************************************/
570 * Initiates a transfer from a device to memory.
573 * 0 Transfer was started successfully
574 * -EINVAL Invalid device type for this kind of transfer
575 * (i.e. the device is _MEM_TO_DEV and not _DEV_TO_MEM)
577 /****************************************************************************/
579 static inline int dma_transfer_from_device(DMA_Handle_t handle
, /* DMA Handle */
580 dma_addr_t srcData
, /* Pointer to the device data address (physical address) */
581 dma_addr_t dstData
, /* Place to store data retrieved from the device (physical address) */
582 size_t numBytes
/* Number of bytes to retrieve from the device */
584 return dma_transfer(handle
,
585 dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM
,
586 srcData
, dstData
, numBytes
);
589 /****************************************************************************/
591 * Initiates a memory to memory transfer.
594 * 0 Transfer was started successfully
595 * -EINVAL Invalid device type for this kind of transfer
596 * (i.e. the device wasn't DMA_DEVICE_MEM_TO_MEM)
598 /****************************************************************************/
600 static inline int dma_transfer_mem_to_mem(DMA_Handle_t handle
, /* DMA Handle */
601 dma_addr_t srcData
, /* Place to transfer data from (physical address) */
602 dma_addr_t dstData
, /* Place to transfer data to (physical address) */
603 size_t numBytes
/* Number of bytes to transfer */
605 return dma_transfer(handle
,
606 dmacHw_TRANSFER_TYPE_MEM_TO_MEM
,
607 srcData
, dstData
, numBytes
);
610 /****************************************************************************/
612 * Set the callback function which will be called when a transfer completes.
613 * If a NULL callback function is set, then no callback will occur.
615 * @note @a devHandler will be called from IRQ context.
619 * -ENODEV - Device handed in is invalid.
621 /****************************************************************************/
623 int dma_set_device_handler(DMA_Device_t dev
, /* Device to set the callback for. */
624 DMA_DeviceHandler_t devHandler
, /* Function to call when the DMA completes */
625 void *userData
/* Pointer which will be passed to devHandler. */
630 #endif /* ASM_ARM_ARCH_BCMRING_DMA_H */