ARM: 5647/1: bcmring: add bcmring dma.h and dma_device.c
authorLeo Chen <leochen@broadcom.com>
Fri, 7 Aug 2009 19:00:39 +0000 (20:00 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Sat, 15 Aug 2009 15:01:40 +0000 (16:01 +0100)
add bcmring dma.h and dma_device.c

Signed-off-by: Leo Chen <leochen@broadcom.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
arch/arm/mach-bcmring/dma_device.c [new file with mode: 0644]
arch/arm/mach-bcmring/include/mach/dma.h [new file with mode: 0644]

diff --git a/arch/arm/mach-bcmring/dma_device.c b/arch/arm/mach-bcmring/dma_device.c
new file mode 100644 (file)
index 0000000..ca0ad73
--- /dev/null
@@ -0,0 +1,593 @@
+/*****************************************************************************
+* Copyright 2004 - 2008 Broadcom Corporation.  All rights reserved.
+*
+* Unless you and Broadcom execute a separate written software license
+* agreement governing use of this software, this software is licensed to you
+* under the terms of the GNU General Public License version 2, available at
+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
+*
+* Notwithstanding the above, under no circumstances may you combine this
+* software in any way with any other Broadcom software provided under a
+* license other than the GPL, without Broadcom's express prior written
+* consent.
+*****************************************************************************/
+
+/****************************************************************************/
+/**
+*   @file   dma_device.c
+*
+*   @brief  private array of DMA_DeviceAttribute_t
+*/
+/****************************************************************************/
+
+DMA_DeviceAttribute_t DMA_gDeviceAttribute[DMA_NUM_DEVICE_ENTRIES] = {
+       [DMA_DEVICE_MEM_TO_MEM] =       /* MEM 2 MEM */
+       {
+        .flags = DMA_DEVICE_FLAG_ON_DMA0 | DMA_DEVICE_FLAG_ON_DMA1,
+        .name = "mem-to-mem",
+        .config = {
+                   .srcUpdate = dmacHw_SRC_ADDRESS_UPDATE_MODE_INC,
+                   .dstUpdate = dmacHw_DST_ADDRESS_UPDATE_MODE_INC,
+                   .transferType = dmacHw_TRANSFER_TYPE_MEM_TO_MEM,
+                   .transferMode = dmacHw_TRANSFER_MODE_PERREQUEST,
+                   .srcMasterInterface = dmacHw_SRC_MASTER_INTERFACE_1,
+                   .dstMasterInterface = dmacHw_DST_MASTER_INTERFACE_1,
+                   .completeTransferInterrupt = dmacHw_INTERRUPT_ENABLE,
+                   .errorInterrupt = dmacHw_INTERRUPT_ENABLE,
+                   .channelPriority = dmacHw_CHANNEL_PRIORITY_7,
+                   .srcMaxTransactionWidth = dmacHw_SRC_TRANSACTION_WIDTH_64,
+                   .dstMaxTransactionWidth = dmacHw_DST_TRANSACTION_WIDTH_64,
+
+                   },
+        },
+       [DMA_DEVICE_VPM_MEM_TO_MEM] =   /* VPM */
+       {
+        .flags = DMA_DEVICE_FLAG_IS_DEDICATED | DMA_DEVICE_FLAG_NO_ISR,
+        .name = "vpm",
+        .dedicatedController = 0,
+        .dedicatedChannel = 0,
+        /* reserve DMA0:0 for VPM */
+        },
+       [DMA_DEVICE_NAND_MEM_TO_MEM] =  /* NAND */
+       {
+        .flags = DMA_DEVICE_FLAG_ON_DMA0 | DMA_DEVICE_FLAG_ON_DMA1,
+        .name = "nand",
+        .config = {
+                   .srcPeripheralPort = 0,
+                   .dstPeripheralPort = 0,
+                   .srcStatusRegisterAddress = 0x00000000,
+                   .dstStatusRegisterAddress = 0x00000000,
+                   .transferType = dmacHw_TRANSFER_TYPE_MEM_TO_MEM,
+                   .srcMasterInterface = dmacHw_SRC_MASTER_INTERFACE_1,
+                   .dstMasterInterface = dmacHw_DST_MASTER_INTERFACE_1,
+                   .srcMaxTransactionWidth = dmacHw_SRC_TRANSACTION_WIDTH_32,
+                   .dstMaxTransactionWidth = dmacHw_DST_TRANSACTION_WIDTH_32,
+                   .srcMaxBurstWidth = dmacHw_SRC_BURST_WIDTH_4,
+                   .dstMaxBurstWidth = dmacHw_DST_BURST_WIDTH_4,
+                   .completeTransferInterrupt = dmacHw_INTERRUPT_ENABLE,
+                   .errorInterrupt = dmacHw_INTERRUPT_ENABLE,
+                   .channelPriority = dmacHw_CHANNEL_PRIORITY_6,
+                   },
+        },
+       [DMA_DEVICE_PIF_MEM_TO_DEV] =   /* PIF TX */
+       {
+        .flags = DMA_DEVICE_FLAG_ON_DMA0 | DMA_DEVICE_FLAG_ON_DMA1
+        | DMA_DEVICE_FLAG_ALLOW_LARGE_FIFO
+        | DMA_DEVICE_FLAG_ALLOC_DMA1_FIRST | DMA_DEVICE_FLAG_PORT_PER_DMAC,
+        .name = "pif_tx",
+        .dmacPort = {14, 5},
+        .config = {
+                   .srcPeripheralPort = 0,     /* SRC: memory */
+                   /* dstPeripheralPort          = 5 or 14 */
+                   .srcStatusRegisterAddress = 0x00000000,
+                   .dstStatusRegisterAddress = 0x00000000,
+                   .srcUpdate = dmacHw_SRC_ADDRESS_UPDATE_MODE_INC,
+                   .dstUpdate = dmacHw_DST_ADDRESS_UPDATE_MODE_INC,
+                   .transferType = dmacHw_TRANSFER_TYPE_MEM_TO_PERIPHERAL,
+                   .srcMasterInterface = dmacHw_SRC_MASTER_INTERFACE_1,
+                   .dstMasterInterface = dmacHw_DST_MASTER_INTERFACE_2,
+                   .completeTransferInterrupt = dmacHw_INTERRUPT_ENABLE,
+                   .errorInterrupt = dmacHw_INTERRUPT_ENABLE,
+                   .channelPriority = dmacHw_CHANNEL_PRIORITY_7,
+                   .srcMaxTransactionWidth = dmacHw_SRC_TRANSACTION_WIDTH_64,
+                   .dstMaxTransactionWidth = dmacHw_DST_TRANSACTION_WIDTH_32,
+                   .srcMaxBurstWidth = dmacHw_SRC_BURST_WIDTH_8,
+                   .dstMaxBurstWidth = dmacHw_DST_BURST_WIDTH_8,
+                   .maxDataPerBlock = 16256,
+                   },
+        },
+       [DMA_DEVICE_PIF_DEV_TO_MEM] =   /* PIF RX */
+       {
+        .flags = DMA_DEVICE_FLAG_ON_DMA0 | DMA_DEVICE_FLAG_ON_DMA1
+        | DMA_DEVICE_FLAG_ALLOW_LARGE_FIFO
+        /* DMA_DEVICE_FLAG_ALLOC_DMA1_FIRST */
+        | DMA_DEVICE_FLAG_PORT_PER_DMAC,
+        .name = "pif_rx",
+        .dmacPort = {14, 5},
+        .config = {
+                   /* srcPeripheralPort          = 5 or 14 */
+                   .dstPeripheralPort = 0,     /* DST: memory */
+                   .srcStatusRegisterAddress = 0x00000000,
+                   .dstStatusRegisterAddress = 0x00000000,
+                   .srcUpdate = dmacHw_SRC_ADDRESS_UPDATE_MODE_INC,
+                   .dstUpdate = dmacHw_DST_ADDRESS_UPDATE_MODE_INC,
+                   .transferType = dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM,
+                   .srcMasterInterface = dmacHw_SRC_MASTER_INTERFACE_2,
+                   .dstMasterInterface = dmacHw_DST_MASTER_INTERFACE_1,
+                   .completeTransferInterrupt = dmacHw_INTERRUPT_ENABLE,
+                   .errorInterrupt = dmacHw_INTERRUPT_ENABLE,
+                   .channelPriority = dmacHw_CHANNEL_PRIORITY_7,
+                   .srcMaxTransactionWidth = dmacHw_SRC_TRANSACTION_WIDTH_32,
+                   .dstMaxTransactionWidth = dmacHw_DST_TRANSACTION_WIDTH_64,
+                   .srcMaxBurstWidth = dmacHw_SRC_BURST_WIDTH_8,
+                   .dstMaxBurstWidth = dmacHw_DST_BURST_WIDTH_8,
+                   .maxDataPerBlock = 16256,
+                   },
+        },
+       [DMA_DEVICE_I2S0_DEV_TO_MEM] =  /* I2S RX */
+       {
+        .flags = DMA_DEVICE_FLAG_ON_DMA0,
+        .name = "i2s0_rx",
+        .config = {
+                   .srcPeripheralPort = 0,     /* SRC: I2S0 */
+                   .dstPeripheralPort = 0,     /* DST: memory */
+                   .srcStatusRegisterAddress = 0,
+                   .dstStatusRegisterAddress = 0,
+                   .transferType = dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM,
+                   .srcMasterInterface = dmacHw_SRC_MASTER_INTERFACE_1,
+                   .dstMasterInterface = dmacHw_DST_MASTER_INTERFACE_1,
+                   .srcMaxTransactionWidth = dmacHw_SRC_TRANSACTION_WIDTH_16,
+                   .dstMaxTransactionWidth = dmacHw_DST_TRANSACTION_WIDTH_64,
+                   .srcMaxBurstWidth = dmacHw_SRC_BURST_WIDTH_4,
+                   .dstMaxBurstWidth = dmacHw_DST_BURST_WIDTH_0,
+                   .blockTransferInterrupt = dmacHw_INTERRUPT_ENABLE,
+                   .completeTransferInterrupt = dmacHw_INTERRUPT_DISABLE,
+                   .errorInterrupt = dmacHw_INTERRUPT_ENABLE,
+                   .channelPriority = dmacHw_CHANNEL_PRIORITY_7,
+                   .transferMode = dmacHw_TRANSFER_MODE_CONTINUOUS,
+                   },
+        },
+       [DMA_DEVICE_I2S0_MEM_TO_DEV] =  /* I2S TX */
+       {
+        .flags = DMA_DEVICE_FLAG_ON_DMA0,
+        .name = "i2s0_tx",
+        .config = {
+                   .srcPeripheralPort = 0,     /* SRC: memory */
+                   .dstPeripheralPort = 1,     /* DST: I2S0 */
+                   .srcStatusRegisterAddress = 0,
+                   .dstStatusRegisterAddress = 0,
+                   .transferType = dmacHw_TRANSFER_TYPE_MEM_TO_PERIPHERAL,
+                   .srcMasterInterface = dmacHw_SRC_MASTER_INTERFACE_1,
+                   .dstMasterInterface = dmacHw_DST_MASTER_INTERFACE_1,
+                   .srcMaxTransactionWidth = dmacHw_SRC_TRANSACTION_WIDTH_64,
+                   .dstMaxTransactionWidth = dmacHw_DST_TRANSACTION_WIDTH_16,
+                   .srcMaxBurstWidth = dmacHw_SRC_BURST_WIDTH_0,
+                   .dstMaxBurstWidth = dmacHw_DST_BURST_WIDTH_4,
+                   .blockTransferInterrupt = dmacHw_INTERRUPT_DISABLE,
+                   .completeTransferInterrupt = dmacHw_INTERRUPT_ENABLE,
+                   .errorInterrupt = dmacHw_INTERRUPT_ENABLE,
+                   .channelPriority = dmacHw_CHANNEL_PRIORITY_7,
+                   .transferMode = dmacHw_TRANSFER_MODE_PERREQUEST,
+                   },
+        },
+       [DMA_DEVICE_I2S1_DEV_TO_MEM] =  /* I2S1 RX */
+       {
+        .flags = DMA_DEVICE_FLAG_ON_DMA1,
+        .name = "i2s1_rx",
+        .config = {
+                   .srcPeripheralPort = 2,     /* SRC: I2S1 */
+                   .dstPeripheralPort = 0,     /* DST: memory */
+                   .srcStatusRegisterAddress = 0,
+                   .dstStatusRegisterAddress = 0,
+                   .transferType = dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM,
+                   .srcMasterInterface = dmacHw_SRC_MASTER_INTERFACE_1,
+                   .dstMasterInterface = dmacHw_DST_MASTER_INTERFACE_1,
+                   .srcMaxTransactionWidth = dmacHw_SRC_TRANSACTION_WIDTH_16,
+                   .dstMaxTransactionWidth = dmacHw_DST_TRANSACTION_WIDTH_64,
+                   .srcMaxBurstWidth = dmacHw_SRC_BURST_WIDTH_4,
+                   .dstMaxBurstWidth = dmacHw_DST_BURST_WIDTH_0,
+                   .blockTransferInterrupt = dmacHw_INTERRUPT_ENABLE,
+                   .completeTransferInterrupt = dmacHw_INTERRUPT_DISABLE,
+                   .errorInterrupt = dmacHw_INTERRUPT_ENABLE,
+                   .channelPriority = dmacHw_CHANNEL_PRIORITY_7,
+                   .transferMode = dmacHw_TRANSFER_MODE_CONTINUOUS,
+                   },
+        },
+       [DMA_DEVICE_I2S1_MEM_TO_DEV] =  /* I2S1 TX */
+       {
+        .flags = DMA_DEVICE_FLAG_ON_DMA1,
+        .name = "i2s1_tx",
+        .config = {
+                   .srcPeripheralPort = 0,     /* SRC: memory */
+                   .dstPeripheralPort = 3,     /* DST: I2S1 */
+                   .srcStatusRegisterAddress = 0,
+                   .dstStatusRegisterAddress = 0,
+                   .transferType = dmacHw_TRANSFER_TYPE_MEM_TO_PERIPHERAL,
+                   .srcMasterInterface = dmacHw_SRC_MASTER_INTERFACE_1,
+                   .dstMasterInterface = dmacHw_DST_MASTER_INTERFACE_1,
+                   .srcMaxTransactionWidth = dmacHw_SRC_TRANSACTION_WIDTH_64,
+                   .dstMaxTransactionWidth = dmacHw_DST_TRANSACTION_WIDTH_16,
+                   .srcMaxBurstWidth = dmacHw_SRC_BURST_WIDTH_0,
+                   .dstMaxBurstWidth = dmacHw_DST_BURST_WIDTH_4,
+                   .blockTransferInterrupt = dmacHw_INTERRUPT_DISABLE,
+                   .completeTransferInterrupt = dmacHw_INTERRUPT_ENABLE,
+                   .errorInterrupt = dmacHw_INTERRUPT_ENABLE,
+                   .channelPriority = dmacHw_CHANNEL_PRIORITY_7,
+                   .transferMode = dmacHw_TRANSFER_MODE_PERREQUEST,
+                   },
+        },
+       [DMA_DEVICE_ESW_MEM_TO_DEV] =   /* ESW TX */
+       {
+        .name = "esw_tx",
+        .flags = DMA_DEVICE_FLAG_IS_DEDICATED,
+        .dedicatedController = 1,
+        .dedicatedChannel = 3,
+        .config = {
+                   .srcPeripheralPort = 0,     /* SRC: memory */
+                   .dstPeripheralPort = 1,     /* DST: ESW (MTP) */
+                   .completeTransferInterrupt = dmacHw_INTERRUPT_ENABLE,
+                   .errorInterrupt = dmacHw_INTERRUPT_DISABLE,
+                   /* DMAx_AHB_SSTATARy */
+                   .srcStatusRegisterAddress = 0x00000000,
+                   /* DMAx_AHB_DSTATARy */
+                   .dstStatusRegisterAddress = 0x30490010,
+                   /* DMAx_AHB_CFGy */
+                   .channelPriority = dmacHw_CHANNEL_PRIORITY_7,
+                   /* DMAx_AHB_CTLy */
+                   .srcMasterInterface = dmacHw_SRC_MASTER_INTERFACE_2,
+                   .dstMasterInterface = dmacHw_DST_MASTER_INTERFACE_1,
+                   .transferType = dmacHw_TRANSFER_TYPE_MEM_TO_PERIPHERAL,
+                   .srcMaxBurstWidth = dmacHw_SRC_BURST_WIDTH_0,
+                   .dstMaxBurstWidth = dmacHw_DST_BURST_WIDTH_8,
+                   .srcUpdate = dmacHw_SRC_ADDRESS_UPDATE_MODE_INC,
+                   .dstUpdate = dmacHw_DST_ADDRESS_UPDATE_MODE_INC,
+                   .srcMaxTransactionWidth = dmacHw_SRC_TRANSACTION_WIDTH_64,
+                   .dstMaxTransactionWidth = dmacHw_DST_TRANSACTION_WIDTH_64,
+                   },
+        },
+       [DMA_DEVICE_ESW_DEV_TO_MEM] =   /* ESW RX */
+       {
+        .name = "esw_rx",
+        .flags = DMA_DEVICE_FLAG_IS_DEDICATED,
+        .dedicatedController = 1,
+        .dedicatedChannel = 2,
+        .config = {
+                   .srcPeripheralPort = 0,     /* SRC: ESW (PTM) */
+                   .dstPeripheralPort = 0,     /* DST: memory */
+                   .completeTransferInterrupt = dmacHw_INTERRUPT_ENABLE,
+                   .errorInterrupt = dmacHw_INTERRUPT_DISABLE,
+                   /* DMAx_AHB_SSTATARy */
+                   .srcStatusRegisterAddress = 0x30480010,
+                   /* DMAx_AHB_DSTATARy */
+                   .dstStatusRegisterAddress = 0x00000000,
+                   /* DMAx_AHB_CFGy */
+                   .channelPriority = dmacHw_CHANNEL_PRIORITY_7,
+                   /* DMAx_AHB_CTLy */
+                   .srcMasterInterface = dmacHw_SRC_MASTER_INTERFACE_2,
+                   .dstMasterInterface = dmacHw_DST_MASTER_INTERFACE_1,
+                   .transferType = dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM,
+                   .srcMaxBurstWidth = dmacHw_SRC_BURST_WIDTH_8,
+                   .dstMaxBurstWidth = dmacHw_DST_BURST_WIDTH_0,
+                   .srcUpdate = dmacHw_SRC_ADDRESS_UPDATE_MODE_INC,
+                   .dstUpdate = dmacHw_DST_ADDRESS_UPDATE_MODE_INC,
+                   .srcMaxTransactionWidth = dmacHw_SRC_TRANSACTION_WIDTH_64,
+                   .dstMaxTransactionWidth = dmacHw_DST_TRANSACTION_WIDTH_64,
+                   },
+        },
+       [DMA_DEVICE_APM_CODEC_A_DEV_TO_MEM] =   /* APM Codec A Ingress */
+       {
+        .flags = DMA_DEVICE_FLAG_ON_DMA0,
+        .name = "apm_a_rx",
+        .config = {
+                   .srcPeripheralPort = 2,     /* SRC: Codec A Ingress FIFO */
+                   .dstPeripheralPort = 0,     /* DST: memory */
+                   .srcStatusRegisterAddress = 0x00000000,
+                   .dstStatusRegisterAddress = 0x00000000,
+                   .srcUpdate = dmacHw_SRC_ADDRESS_UPDATE_MODE_INC,
+                   .dstUpdate = dmacHw_DST_ADDRESS_UPDATE_MODE_INC,
+                   .transferType = dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM,
+                   .srcMasterInterface = dmacHw_SRC_MASTER_INTERFACE_2,
+                   .dstMasterInterface = dmacHw_DST_MASTER_INTERFACE_1,
+                   .blockTransferInterrupt = dmacHw_INTERRUPT_ENABLE,
+                   .completeTransferInterrupt = dmacHw_INTERRUPT_DISABLE,
+                   .errorInterrupt = dmacHw_INTERRUPT_ENABLE,
+                   .channelPriority = dmacHw_CHANNEL_PRIORITY_7,
+                   .srcMaxTransactionWidth = dmacHw_SRC_TRANSACTION_WIDTH_32,
+                   .dstMaxTransactionWidth = dmacHw_DST_TRANSACTION_WIDTH_64,
+                   .srcMaxBurstWidth = dmacHw_SRC_BURST_WIDTH_4,
+                   .dstMaxBurstWidth = dmacHw_DST_BURST_WIDTH_4,
+                   .transferMode = dmacHw_TRANSFER_MODE_CONTINUOUS,
+                   },
+        },
+       [DMA_DEVICE_APM_CODEC_A_MEM_TO_DEV] =   /* APM Codec A Egress */
+       {
+        .flags = DMA_DEVICE_FLAG_ON_DMA0,
+        .name = "apm_a_tx",
+        .config = {
+                   .srcPeripheralPort = 0,     /* SRC: memory */
+                   .dstPeripheralPort = 3,     /* DST: Codec A Egress FIFO */
+                   .srcStatusRegisterAddress = 0x00000000,
+                   .dstStatusRegisterAddress = 0x00000000,
+                   .srcUpdate = dmacHw_SRC_ADDRESS_UPDATE_MODE_INC,
+                   .dstUpdate = dmacHw_DST_ADDRESS_UPDATE_MODE_INC,
+                   .transferType = dmacHw_TRANSFER_TYPE_MEM_TO_PERIPHERAL,
+                   .srcMasterInterface = dmacHw_SRC_MASTER_INTERFACE_1,
+                   .dstMasterInterface = dmacHw_DST_MASTER_INTERFACE_2,
+                   .blockTransferInterrupt = dmacHw_INTERRUPT_DISABLE,
+                   .completeTransferInterrupt = dmacHw_INTERRUPT_ENABLE,
+                   .errorInterrupt = dmacHw_INTERRUPT_ENABLE,
+                   .channelPriority = dmacHw_CHANNEL_PRIORITY_7,
+                   .srcMaxTransactionWidth = dmacHw_SRC_TRANSACTION_WIDTH_64,
+                   .dstMaxTransactionWidth = dmacHw_DST_TRANSACTION_WIDTH_32,
+                   .srcMaxBurstWidth = dmacHw_SRC_BURST_WIDTH_4,
+                   .dstMaxBurstWidth = dmacHw_DST_BURST_WIDTH_4,
+                   .transferMode = dmacHw_TRANSFER_MODE_PERREQUEST,
+                   },
+        },
+       [DMA_DEVICE_APM_CODEC_B_DEV_TO_MEM] =   /* APM Codec B Ingress */
+       {
+        .flags = DMA_DEVICE_FLAG_ON_DMA0,
+        .name = "apm_b_rx",
+        .config = {
+                   .srcPeripheralPort = 4,     /* SRC: Codec B Ingress FIFO */
+                   .dstPeripheralPort = 0,     /* DST: memory */
+                   .srcStatusRegisterAddress = 0x00000000,
+                   .dstStatusRegisterAddress = 0x00000000,
+                   .srcUpdate = dmacHw_SRC_ADDRESS_UPDATE_MODE_INC,
+                   .dstUpdate = dmacHw_DST_ADDRESS_UPDATE_MODE_INC,
+                   .transferType = dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM,
+                   .srcMasterInterface = dmacHw_SRC_MASTER_INTERFACE_2,
+                   .dstMasterInterface = dmacHw_DST_MASTER_INTERFACE_1,
+                   .blockTransferInterrupt = dmacHw_INTERRUPT_ENABLE,
+                   .completeTransferInterrupt = dmacHw_INTERRUPT_DISABLE,
+                   .errorInterrupt = dmacHw_INTERRUPT_ENABLE,
+                   .channelPriority = dmacHw_CHANNEL_PRIORITY_7,
+                   .srcMaxTransactionWidth = dmacHw_SRC_TRANSACTION_WIDTH_32,
+                   .dstMaxTransactionWidth = dmacHw_DST_TRANSACTION_WIDTH_64,
+                   .srcMaxBurstWidth = dmacHw_SRC_BURST_WIDTH_4,
+                   .dstMaxBurstWidth = dmacHw_DST_BURST_WIDTH_4,
+                   .transferMode = dmacHw_TRANSFER_MODE_CONTINUOUS,
+                   },
+        },
+       [DMA_DEVICE_APM_CODEC_B_MEM_TO_DEV] =   /* APM Codec B Egress */
+       {
+        .flags = DMA_DEVICE_FLAG_ON_DMA0,
+        .name = "apm_b_tx",
+        .config = {
+                   .srcPeripheralPort = 0,     /* SRC: memory */
+                   .dstPeripheralPort = 5,     /* DST: Codec B Egress FIFO */
+                   .srcStatusRegisterAddress = 0x00000000,
+                   .dstStatusRegisterAddress = 0x00000000,
+                   .srcUpdate = dmacHw_SRC_ADDRESS_UPDATE_MODE_INC,
+                   .dstUpdate = dmacHw_DST_ADDRESS_UPDATE_MODE_INC,
+                   .transferType = dmacHw_TRANSFER_TYPE_MEM_TO_PERIPHERAL,
+                   .srcMasterInterface = dmacHw_SRC_MASTER_INTERFACE_1,
+                   .dstMasterInterface = dmacHw_DST_MASTER_INTERFACE_2,
+                   .blockTransferInterrupt = dmacHw_INTERRUPT_DISABLE,
+                   .completeTransferInterrupt = dmacHw_INTERRUPT_ENABLE,
+                   .errorInterrupt = dmacHw_INTERRUPT_ENABLE,
+                   .channelPriority = dmacHw_CHANNEL_PRIORITY_7,
+                   .srcMaxTransactionWidth = dmacHw_SRC_TRANSACTION_WIDTH_64,
+                   .dstMaxTransactionWidth = dmacHw_DST_TRANSACTION_WIDTH_32,
+                   .srcMaxBurstWidth = dmacHw_SRC_BURST_WIDTH_4,
+                   .dstMaxBurstWidth = dmacHw_DST_BURST_WIDTH_4,
+                   .transferMode = dmacHw_TRANSFER_MODE_PERREQUEST,
+                   },
+        },
+       [DMA_DEVICE_APM_CODEC_C_DEV_TO_MEM] =   /* APM Codec C Ingress */
+       {
+        .flags = DMA_DEVICE_FLAG_ON_DMA1,
+        .name = "apm_c_rx",
+        .config = {
+                   .srcPeripheralPort = 4,     /* SRC: Codec C Ingress FIFO */
+                   .dstPeripheralPort = 0,     /* DST: memory */
+                   .srcStatusRegisterAddress = 0x00000000,
+                   .dstStatusRegisterAddress = 0x00000000,
+                   .srcUpdate = dmacHw_SRC_ADDRESS_UPDATE_MODE_INC,
+                   .dstUpdate = dmacHw_DST_ADDRESS_UPDATE_MODE_INC,
+                   .transferType = dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM,
+                   .srcMasterInterface = dmacHw_SRC_MASTER_INTERFACE_2,
+                   .dstMasterInterface = dmacHw_DST_MASTER_INTERFACE_1,
+                   .blockTransferInterrupt = dmacHw_INTERRUPT_ENABLE,
+                   .completeTransferInterrupt = dmacHw_INTERRUPT_DISABLE,
+                   .errorInterrupt = dmacHw_INTERRUPT_ENABLE,
+                   .channelPriority = dmacHw_CHANNEL_PRIORITY_7,
+                   .srcMaxTransactionWidth = dmacHw_SRC_TRANSACTION_WIDTH_32,
+                   .dstMaxTransactionWidth = dmacHw_DST_TRANSACTION_WIDTH_64,
+                   .srcMaxBurstWidth = dmacHw_SRC_BURST_WIDTH_4,
+                   .dstMaxBurstWidth = dmacHw_DST_BURST_WIDTH_4,
+                   .transferMode = dmacHw_TRANSFER_MODE_CONTINUOUS,
+                   },
+        },
+       [DMA_DEVICE_APM_PCM0_DEV_TO_MEM] =      /* PCM0 RX */
+       {
+        .flags = DMA_DEVICE_FLAG_ON_DMA0,
+        .name = "pcm0_rx",
+        .config = {
+                   .srcPeripheralPort = 12,    /* SRC: PCM0 */
+                   .dstPeripheralPort = 0,     /* DST: memory */
+                   .srcStatusRegisterAddress = 0,
+                   .dstStatusRegisterAddress = 0,
+                   .transferType = dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM,
+                   .srcMasterInterface = dmacHw_SRC_MASTER_INTERFACE_2,
+                   .dstMasterInterface = dmacHw_DST_MASTER_INTERFACE_1,
+                   .srcMaxTransactionWidth = dmacHw_SRC_TRANSACTION_WIDTH_32,
+                   .dstMaxTransactionWidth = dmacHw_DST_TRANSACTION_WIDTH_64,
+                   .srcMaxBurstWidth = dmacHw_SRC_BURST_WIDTH_8,
+                   .dstMaxBurstWidth = dmacHw_DST_BURST_WIDTH_4,
+                   .blockTransferInterrupt = dmacHw_INTERRUPT_ENABLE,
+                   .completeTransferInterrupt = dmacHw_INTERRUPT_DISABLE,
+                   .errorInterrupt = dmacHw_INTERRUPT_ENABLE,
+                   .channelPriority = dmacHw_CHANNEL_PRIORITY_7,
+                   .transferMode = dmacHw_TRANSFER_MODE_CONTINUOUS,
+                   },
+        },
+       [DMA_DEVICE_APM_PCM0_MEM_TO_DEV] =      /* PCM0 TX */
+       {
+        .flags = DMA_DEVICE_FLAG_ON_DMA0,
+        .name = "pcm0_tx",
+        .config = {
+                   .srcPeripheralPort = 0,     /* SRC: memory */
+                   .dstPeripheralPort = 13,    /* DST: PCM0 */
+                   .srcStatusRegisterAddress = 0,
+                   .dstStatusRegisterAddress = 0,
+                   .transferType = dmacHw_TRANSFER_TYPE_MEM_TO_PERIPHERAL,
+                   .srcMasterInterface = dmacHw_SRC_MASTER_INTERFACE_1,
+                   .dstMasterInterface = dmacHw_DST_MASTER_INTERFACE_2,
+                   .srcMaxTransactionWidth = dmacHw_SRC_TRANSACTION_WIDTH_64,
+                   .dstMaxTransactionWidth = dmacHw_DST_TRANSACTION_WIDTH_32,
+                   .srcMaxBurstWidth = dmacHw_SRC_BURST_WIDTH_4,
+                   .dstMaxBurstWidth = dmacHw_DST_BURST_WIDTH_8,
+                   .blockTransferInterrupt = dmacHw_INTERRUPT_DISABLE,
+                   .completeTransferInterrupt = dmacHw_INTERRUPT_ENABLE,
+                   .errorInterrupt = dmacHw_INTERRUPT_ENABLE,
+                   .channelPriority = dmacHw_CHANNEL_PRIORITY_7,
+                   .transferMode = dmacHw_TRANSFER_MODE_PERREQUEST,
+                   },
+        },
+       [DMA_DEVICE_APM_PCM1_DEV_TO_MEM] =      /* PCM1 RX */
+       {
+        .flags = DMA_DEVICE_FLAG_ON_DMA1,
+        .name = "pcm1_rx",
+        .config = {
+                   .srcPeripheralPort = 14,    /* SRC: PCM1 */
+                   .dstPeripheralPort = 0,     /* DST: memory */
+                   .srcStatusRegisterAddress = 0,
+                   .dstStatusRegisterAddress = 0,
+                   .transferType = dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM,
+                   .srcMasterInterface = dmacHw_SRC_MASTER_INTERFACE_2,
+                   .dstMasterInterface = dmacHw_DST_MASTER_INTERFACE_1,
+                   .srcMaxTransactionWidth = dmacHw_SRC_TRANSACTION_WIDTH_32,
+                   .dstMaxTransactionWidth = dmacHw_DST_TRANSACTION_WIDTH_64,
+                   .srcMaxBurstWidth = dmacHw_SRC_BURST_WIDTH_8,
+                   .dstMaxBurstWidth = dmacHw_DST_BURST_WIDTH_4,
+                   .blockTransferInterrupt = dmacHw_INTERRUPT_ENABLE,
+                   .completeTransferInterrupt = dmacHw_INTERRUPT_DISABLE,
+                   .errorInterrupt = dmacHw_INTERRUPT_ENABLE,
+                   .channelPriority = dmacHw_CHANNEL_PRIORITY_7,
+                   .transferMode = dmacHw_TRANSFER_MODE_CONTINUOUS,
+                   },
+        },
+       [DMA_DEVICE_APM_PCM1_MEM_TO_DEV] =      /* PCM1 TX */
+       {
+        .flags = DMA_DEVICE_FLAG_ON_DMA1,
+        .name = "pcm1_tx",
+        .config = {
+                   .srcPeripheralPort = 0,     /* SRC: memory */
+                   .dstPeripheralPort = 15,    /* DST: PCM1 */
+                   .srcStatusRegisterAddress = 0,
+                   .dstStatusRegisterAddress = 0,
+                   .transferType = dmacHw_TRANSFER_TYPE_MEM_TO_PERIPHERAL,
+                   .srcMasterInterface = dmacHw_SRC_MASTER_INTERFACE_1,
+                   .dstMasterInterface = dmacHw_DST_MASTER_INTERFACE_2,
+                   .srcMaxTransactionWidth = dmacHw_SRC_TRANSACTION_WIDTH_64,
+                   .dstMaxTransactionWidth = dmacHw_DST_TRANSACTION_WIDTH_32,
+                   .srcMaxBurstWidth = dmacHw_SRC_BURST_WIDTH_4,
+                   .dstMaxBurstWidth = dmacHw_DST_BURST_WIDTH_8,
+                   .blockTransferInterrupt = dmacHw_INTERRUPT_DISABLE,
+                   .completeTransferInterrupt = dmacHw_INTERRUPT_ENABLE,
+                   .errorInterrupt = dmacHw_INTERRUPT_ENABLE,
+                   .channelPriority = dmacHw_CHANNEL_PRIORITY_7,
+                   .transferMode = dmacHw_TRANSFER_MODE_PERREQUEST,
+                   },
+        },
+       [DMA_DEVICE_SPUM_DEV_TO_MEM] =  /* SPUM RX */
+       {
+        .flags = DMA_DEVICE_FLAG_ON_DMA0 | DMA_DEVICE_FLAG_ON_DMA1,
+        .name = "spum_rx",
+        .config = {
+                   .srcPeripheralPort = 6,     /* SRC: Codec A Ingress FIFO */
+                   .dstPeripheralPort = 0,     /* DST: memory */
+                   .srcStatusRegisterAddress = 0x00000000,
+                   .dstStatusRegisterAddress = 0x00000000,
+                   .srcUpdate = dmacHw_SRC_ADDRESS_UPDATE_MODE_INC,
+                   .dstUpdate = dmacHw_DST_ADDRESS_UPDATE_MODE_INC,
+                   .transferType = dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM,
+                   .srcMasterInterface = dmacHw_SRC_MASTER_INTERFACE_2,
+                   .dstMasterInterface = dmacHw_DST_MASTER_INTERFACE_1,
+                   .blockTransferInterrupt = dmacHw_INTERRUPT_DISABLE,
+                   .completeTransferInterrupt = dmacHw_INTERRUPT_ENABLE,
+                   .errorInterrupt = dmacHw_INTERRUPT_ENABLE,
+                   .channelPriority = dmacHw_CHANNEL_PRIORITY_7,
+                   .srcMaxTransactionWidth = dmacHw_SRC_TRANSACTION_WIDTH_32,
+                   .dstMaxTransactionWidth = dmacHw_DST_TRANSACTION_WIDTH_32,
+                   /* Busrt size **MUST** be 16 for SPUM to work */
+                   .srcMaxBurstWidth = dmacHw_SRC_BURST_WIDTH_16,
+                   .dstMaxBurstWidth = dmacHw_DST_BURST_WIDTH_16,
+                   .transferMode = dmacHw_TRANSFER_MODE_PERREQUEST,
+                   /* on the RX side, SPU needs to be the flow controller */
+                   .flowControler = dmacHw_FLOW_CONTROL_PERIPHERAL,
+                   },
+        },
+       [DMA_DEVICE_SPUM_MEM_TO_DEV] =  /* SPUM TX */
+       {
+        .flags = DMA_DEVICE_FLAG_ON_DMA0 | DMA_DEVICE_FLAG_ON_DMA1,
+        .name = "spum_tx",
+        .config = {
+                   .srcPeripheralPort = 0,     /* SRC: memory */
+                   .dstPeripheralPort = 7,     /* DST: SPUM */
+                   .srcStatusRegisterAddress = 0x00000000,
+                   .dstStatusRegisterAddress = 0x00000000,
+                   .srcUpdate = dmacHw_SRC_ADDRESS_UPDATE_MODE_INC,
+                   .dstUpdate = dmacHw_DST_ADDRESS_UPDATE_MODE_INC,
+                   .transferType = dmacHw_TRANSFER_TYPE_MEM_TO_PERIPHERAL,
+                   .srcMasterInterface = dmacHw_SRC_MASTER_INTERFACE_1,
+                   .dstMasterInterface = dmacHw_DST_MASTER_INTERFACE_2,
+                   .blockTransferInterrupt = dmacHw_INTERRUPT_DISABLE,
+                   .completeTransferInterrupt = dmacHw_INTERRUPT_ENABLE,
+                   .errorInterrupt = dmacHw_INTERRUPT_ENABLE,
+                   .channelPriority = dmacHw_CHANNEL_PRIORITY_7,
+                   .srcMaxTransactionWidth = dmacHw_SRC_TRANSACTION_WIDTH_32,
+                   .dstMaxTransactionWidth = dmacHw_DST_TRANSACTION_WIDTH_32,
+                   /* Busrt size **MUST** be 16 for SPUM to work */
+                   .srcMaxBurstWidth = dmacHw_SRC_BURST_WIDTH_16,
+                   .dstMaxBurstWidth = dmacHw_DST_BURST_WIDTH_16,
+                   .transferMode = dmacHw_TRANSFER_MODE_PERREQUEST,
+                   },
+        },
+       [DMA_DEVICE_MEM_TO_VRAM] =      /* MEM 2 VRAM */
+       {
+        .flags = DMA_DEVICE_FLAG_ON_DMA0 | DMA_DEVICE_FLAG_ON_DMA1,
+        .name = "mem-to-vram",
+        .config = {
+                   .srcPeripheralPort = 0,     /* SRC: memory */
+                   .srcStatusRegisterAddress = 0x00000000,
+                   .dstStatusRegisterAddress = 0x00000000,
+                   .srcUpdate = dmacHw_SRC_ADDRESS_UPDATE_MODE_INC,
+                   .dstUpdate = dmacHw_DST_ADDRESS_UPDATE_MODE_INC,
+                   .transferType = dmacHw_TRANSFER_TYPE_MEM_TO_MEM,
+                   .srcMasterInterface = dmacHw_SRC_MASTER_INTERFACE_1,
+                   .dstMasterInterface = dmacHw_DST_MASTER_INTERFACE_2,
+                   .completeTransferInterrupt = dmacHw_INTERRUPT_ENABLE,
+                   .errorInterrupt = dmacHw_INTERRUPT_ENABLE,
+                   .channelPriority = dmacHw_CHANNEL_PRIORITY_7,
+                   .srcMaxTransactionWidth = dmacHw_SRC_TRANSACTION_WIDTH_64,
+                   .dstMaxTransactionWidth = dmacHw_DST_TRANSACTION_WIDTH_64,
+                   .srcMaxBurstWidth = dmacHw_SRC_BURST_WIDTH_8,
+                   .dstMaxBurstWidth = dmacHw_DST_BURST_WIDTH_8,
+                   },
+        },
+       [DMA_DEVICE_VRAM_TO_MEM] =      /* VRAM 2 MEM */
+       {
+        .flags = DMA_DEVICE_FLAG_ON_DMA0 | DMA_DEVICE_FLAG_ON_DMA1,
+        .name = "vram-to-mem",
+        .config = {
+                   .dstPeripheralPort = 0,     /* DST: memory */
+                   .srcStatusRegisterAddress = 0x00000000,
+                   .dstStatusRegisterAddress = 0x00000000,
+                   .srcUpdate = dmacHw_SRC_ADDRESS_UPDATE_MODE_INC,
+                   .dstUpdate = dmacHw_DST_ADDRESS_UPDATE_MODE_INC,
+                   .transferType = dmacHw_TRANSFER_TYPE_MEM_TO_MEM,
+                   .srcMasterInterface = dmacHw_SRC_MASTER_INTERFACE_2,
+                   .dstMasterInterface = dmacHw_DST_MASTER_INTERFACE_1,
+                   .completeTransferInterrupt = dmacHw_INTERRUPT_ENABLE,
+                   .errorInterrupt = dmacHw_INTERRUPT_ENABLE,
+                   .channelPriority = dmacHw_CHANNEL_PRIORITY_7,
+                   .srcMaxTransactionWidth = dmacHw_SRC_TRANSACTION_WIDTH_64,
+                   .dstMaxTransactionWidth = dmacHw_DST_TRANSACTION_WIDTH_64,
+                   .srcMaxBurstWidth = dmacHw_SRC_BURST_WIDTH_8,
+                   .dstMaxBurstWidth = dmacHw_DST_BURST_WIDTH_8,
+                   },
+        },
+};
+EXPORT_SYMBOL(DMA_gDeviceAttribute);   /* primarily for dma-test.c */
diff --git a/arch/arm/mach-bcmring/include/mach/dma.h b/arch/arm/mach-bcmring/include/mach/dma.h
new file mode 100644 (file)
index 0000000..847980c
--- /dev/null
@@ -0,0 +1,826 @@
+/*****************************************************************************
+* Copyright 2004 - 2008 Broadcom Corporation.  All rights reserved.
+*
+* Unless you and Broadcom execute a separate written software license
+* agreement governing use of this software, this software is licensed to you
+* under the terms of the GNU General Public License version 2, available at
+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
+*
+* Notwithstanding the above, under no circumstances may you combine this
+* software in any way with any other Broadcom software provided under a
+* license other than the GPL, without Broadcom's express prior written
+* consent.
+*****************************************************************************/
+
+/****************************************************************************/
+/**
+*   @file   dma.h
+*
+*   @brief  API definitions for the linux DMA interface.
+*/
+/****************************************************************************/
+
+#if !defined(ASM_ARM_ARCH_BCMRING_DMA_H)
+#define ASM_ARM_ARCH_BCMRING_DMA_H
+
+/* ---- Include Files ---------------------------------------------------- */
+
+#include <linux/kernel.h>
+#include <linux/wait.h>
+#include <linux/semaphore.h>
+#include <csp/dmacHw.h>
+#include <mach/timer.h>
+#include <linux/scatterlist.h>
+#include <linux/dma-mapping.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/pagemap.h>
+
+/* ---- Constants and Types ---------------------------------------------- */
+
+/* If DMA_DEBUG_TRACK_RESERVATION is set to a non-zero value, then the filename */
+/* and line number of the reservation request will be recorded in the channel table */
+
+#define DMA_DEBUG_TRACK_RESERVATION   1
+
+#define DMA_NUM_CONTROLLERS     2
+#define DMA_NUM_CHANNELS        8      /* per controller */
+
+typedef enum {
+       DMA_DEVICE_MEM_TO_MEM,  /* For memory to memory transfers */
+       DMA_DEVICE_I2S0_DEV_TO_MEM,
+       DMA_DEVICE_I2S0_MEM_TO_DEV,
+       DMA_DEVICE_I2S1_DEV_TO_MEM,
+       DMA_DEVICE_I2S1_MEM_TO_DEV,
+       DMA_DEVICE_APM_CODEC_A_DEV_TO_MEM,
+       DMA_DEVICE_APM_CODEC_A_MEM_TO_DEV,
+       DMA_DEVICE_APM_CODEC_B_DEV_TO_MEM,
+       DMA_DEVICE_APM_CODEC_B_MEM_TO_DEV,
+       DMA_DEVICE_APM_CODEC_C_DEV_TO_MEM,      /* Additional mic input for beam-forming */
+       DMA_DEVICE_APM_PCM0_DEV_TO_MEM,
+       DMA_DEVICE_APM_PCM0_MEM_TO_DEV,
+       DMA_DEVICE_APM_PCM1_DEV_TO_MEM,
+       DMA_DEVICE_APM_PCM1_MEM_TO_DEV,
+       DMA_DEVICE_SPUM_DEV_TO_MEM,
+       DMA_DEVICE_SPUM_MEM_TO_DEV,
+       DMA_DEVICE_SPIH_DEV_TO_MEM,
+       DMA_DEVICE_SPIH_MEM_TO_DEV,
+       DMA_DEVICE_UART_A_DEV_TO_MEM,
+       DMA_DEVICE_UART_A_MEM_TO_DEV,
+       DMA_DEVICE_UART_B_DEV_TO_MEM,
+       DMA_DEVICE_UART_B_MEM_TO_DEV,
+       DMA_DEVICE_PIF_MEM_TO_DEV,
+       DMA_DEVICE_PIF_DEV_TO_MEM,
+       DMA_DEVICE_ESW_DEV_TO_MEM,
+       DMA_DEVICE_ESW_MEM_TO_DEV,
+       DMA_DEVICE_VPM_MEM_TO_MEM,
+       DMA_DEVICE_CLCD_MEM_TO_MEM,
+       DMA_DEVICE_NAND_MEM_TO_MEM,
+       DMA_DEVICE_MEM_TO_VRAM,
+       DMA_DEVICE_VRAM_TO_MEM,
+
+       /* Add new entries before this line. */
+
+       DMA_NUM_DEVICE_ENTRIES,
+       DMA_DEVICE_NONE = 0xff, /* Special value to indicate that no device is currently assigned. */
+
+} DMA_Device_t;
+
+/****************************************************************************
+*
+*   The DMA_Handle_t is the primary object used by callers of the API.
+*
+*****************************************************************************/
+
+#define DMA_INVALID_HANDLE  ((DMA_Handle_t) -1)
+
+typedef int DMA_Handle_t;
+
+/****************************************************************************
+*
+*   The DMA_DescriptorRing_t contains a ring of descriptors which is used
+*   to point to regions of memory.
+*
+*****************************************************************************/
+
+typedef struct {
+       void *virtAddr;         /* Virtual Address of the descriptor ring */
+       dma_addr_t physAddr;    /* Physical address of the descriptor ring */
+       int descriptorsAllocated;       /* Number of descriptors allocated in the descriptor ring */
+       size_t bytesAllocated;  /* Number of bytes allocated in the descriptor ring */
+
+} DMA_DescriptorRing_t;
+
+/****************************************************************************
+*
+*   The DMA_MemType_t and DMA_MemMap_t are helper structures used to setup
+*   DMA chains from a variety of memory sources.
+*
+*****************************************************************************/
+
+#define DMA_MEM_MAP_MIN_SIZE    4096   /* Pages less than this size are better */
+                                       /* off not being DMA'd. */
+
+typedef enum {
+       DMA_MEM_TYPE_NONE,      /* Not a valid setting */
+       DMA_MEM_TYPE_VMALLOC,   /* Memory came from vmalloc call */
+       DMA_MEM_TYPE_KMALLOC,   /* Memory came from kmalloc call */
+       DMA_MEM_TYPE_DMA,       /* Memory came from dma_alloc_xxx call */
+       DMA_MEM_TYPE_USER,      /* Memory came from user space. */
+
+} DMA_MemType_t;
+
+/* A segment represents a physically and virtually contiguous chunk of memory. */
+/* i.e. each segment can be DMA'd */
+/* A user of the DMA code will add memory regions. Each region may need to be */
+/* represented by one or more segments. */
+
+typedef struct {
+       void *virtAddr;         /* Virtual address used for this segment */
+       dma_addr_t physAddr;    /* Physical address this segment maps to */
+       size_t numBytes;        /* Size of the segment, in bytes */
+
+} DMA_Segment_t;
+
+/* A region represents a virtually contiguous chunk of memory, which may be */
+/* made up of multiple segments. */
+
+typedef struct {
+       DMA_MemType_t memType;
+       void *virtAddr;
+       size_t numBytes;
+
+       /* Each region (virtually contiguous) consists of one or more segments. Each */
+       /* segment is virtually and physically contiguous. */
+
+       int numSegmentsUsed;
+       int numSegmentsAllocated;
+       DMA_Segment_t *segment;
+
+       /* When a region corresponds to user memory, we need to lock all of the pages */
+       /* down before we can figure out the physical addresses. The lockedPage array contains */
+       /* the pages that were locked, and which subsequently need to be unlocked once the */
+       /* memory is unmapped. */
+
+       unsigned numLockedPages;
+       struct page **lockedPages;
+
+} DMA_Region_t;
+
+typedef struct {
+       int inUse;              /* Is this mapping currently being used? */
+       struct semaphore lock;  /* Acquired when using this structure */
+       enum dma_data_direction dir;    /* Direction this transfer is intended for */
+
+       /* In the event that we're mapping user memory, we need to know which task */
+       /* the memory is for, so that we can obtain the correct mm locks. */
+
+       struct task_struct *userTask;
+
+       int numRegionsUsed;
+       int numRegionsAllocated;
+       DMA_Region_t *region;
+
+} DMA_MemMap_t;
+
+/****************************************************************************
+*
+*   The DMA_DeviceAttribute_t contains information which describes a
+*   particular DMA device (or peripheral).
+*
+*   It is anticipated that the arrary of DMA_DeviceAttribute_t's will be
+*   statically initialized.
+*
+*****************************************************************************/
+
+/* The device handler is called whenever a DMA operation completes. The reaon */
+/* for it to be called will be a bitmask with one or more of the following bits */
+/* set. */
+
+#define DMA_HANDLER_REASON_BLOCK_COMPLETE       dmacHw_INTERRUPT_STATUS_BLOCK
+#define DMA_HANDLER_REASON_TRANSFER_COMPLETE    dmacHw_INTERRUPT_STATUS_TRANS
+#define DMA_HANDLER_REASON_ERROR                dmacHw_INTERRUPT_STATUS_ERROR
+
+typedef void (*DMA_DeviceHandler_t) (DMA_Device_t dev, int reason,
+                                    void *userData);
+
+#define DMA_DEVICE_FLAG_ON_DMA0             0x00000001
+#define DMA_DEVICE_FLAG_ON_DMA1             0x00000002
+#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 */
+#define DMA_DEVICE_FLAG_ALLOC_DMA1_FIRST    0x00000008 /* If set, allocate from DMA1 before allocating from DMA0 */
+#define DMA_DEVICE_FLAG_IS_DEDICATED        0x00000100
+#define DMA_DEVICE_FLAG_NO_ISR              0x00000200
+#define DMA_DEVICE_FLAG_ALLOW_LARGE_FIFO    0x00000400
+#define DMA_DEVICE_FLAG_IN_USE              0x00000800 /* If set, device is in use on a channel */
+
+/* Note: Some DMA devices can be used from multiple DMA Controllers. The bitmask is used to */
+/*       determine which DMA controllers a given device can be used from, and the interface */
+/*       array determeines the actual interface number to use for a given controller. */
+
+typedef struct {
+       uint32_t flags;         /* Bitmask of DMA_DEVICE_FLAG_xxx constants */
+       uint8_t dedicatedController;    /* Controller number to use if DMA_DEVICE_FLAG_IS_DEDICATED is set. */
+       uint8_t dedicatedChannel;       /* Channel number to use if DMA_DEVICE_FLAG_IS_DEDICATED is set. */
+       const char *name;       /* Will show up in the /proc entry */
+
+       uint32_t dmacPort[DMA_NUM_CONTROLLERS]; /* Specifies the port number when DMA_DEVICE_FLAG_PORT_PER_DMAC flag is set */
+
+       dmacHw_CONFIG_t config; /* Configuration to use when DMA'ing using this device */
+
+       void *userData;         /* Passed to the devHandler */
+       DMA_DeviceHandler_t devHandler; /* Called when DMA operations finish. */
+
+       timer_tick_count_t transferStartTime;   /* Time the current transfer was started */
+
+       /* The following statistical information will be collected and presented in a proc entry. */
+       /* Note: With a contiuous bandwidth of 1 Gb/sec, it would take 584 years to overflow */
+       /*       a 64 bit counter. */
+
+       uint64_t numTransfers;  /* Number of DMA transfers performed */
+       uint64_t transferTicks; /* Total time spent doing DMA transfers (measured in timer_tick_count_t's) */
+       uint64_t transferBytes; /* Total bytes transferred */
+       uint32_t timesBlocked;  /* Number of times a channel was unavailable */
+       uint32_t numBytes;      /* Last transfer size */
+
+       /* It's not possible to free memory which is allocated for the descriptors from within */
+       /* the ISR. So make the presumption that a given device will tend to use the */
+       /* same sized buffers over and over again, and we keep them around. */
+
+       DMA_DescriptorRing_t ring;      /* Ring of descriptors allocated for this device */
+
+       /* We stash away some of the information from the previous transfer. If back-to-back */
+       /* transfers are performed from the same buffer, then we don't have to keep re-initializing */
+       /* the descriptor buffers. */
+
+       uint32_t prevNumBytes;
+       dma_addr_t prevSrcData;
+       dma_addr_t prevDstData;
+
+} DMA_DeviceAttribute_t;
+
+/****************************************************************************
+*
+*   DMA_Channel_t, DMA_Controller_t, and DMA_State_t are really internal
+*   data structures and don't belong in this header file, but are included
+*   merely for discussion.
+*
+*   By the time this is implemented, these structures will be moved out into
+*   the appropriate C source file instead.
+*
+*****************************************************************************/
+
+/****************************************************************************
+*
+*   The DMA_Channel_t contains state information about each DMA channel. Some
+*   of the channels are dedicated. Non-dedicated channels are shared
+*   amongst the other devices.
+*
+*****************************************************************************/
+
+#define DMA_CHANNEL_FLAG_IN_USE         0x00000001
+#define DMA_CHANNEL_FLAG_IS_DEDICATED   0x00000002
+#define DMA_CHANNEL_FLAG_NO_ISR         0x00000004
+#define DMA_CHANNEL_FLAG_LARGE_FIFO     0x00000008
+
+typedef struct {
+       uint32_t flags;         /* bitmask of DMA_CHANNEL_FLAG_xxx constants */
+       DMA_Device_t devType;   /* Device this channel is currently reserved for */
+       DMA_Device_t lastDevType;       /* Device type that used this previously */
+       char name[20];          /* Name passed onto request_irq */
+
+#if (DMA_DEBUG_TRACK_RESERVATION)
+       const char *fileName;   /* Place where channel reservation took place */
+       int lineNum;            /* Place where channel reservation took place */
+#endif
+       dmacHw_HANDLE_t dmacHwHandle;   /* low level channel handle. */
+
+} DMA_Channel_t;
+
+/****************************************************************************
+*
+*   The DMA_Controller_t contains state information about each DMA controller.
+*
+*   The freeChannelQ is stored in the controller data structure rather than
+*   the channel data structure since several of the devices are accessible
+*   from multiple controllers, and there is no way to know which controller
+*   will become available first.
+*
+*****************************************************************************/
+
+typedef struct {
+       DMA_Channel_t channel[DMA_NUM_CHANNELS];
+
+} DMA_Controller_t;
+
+/****************************************************************************
+*
+*   The DMA_Global_t contains all of the global state information used by
+*   the DMA code.
+*
+*   Callers which need to allocate a shared channel will be queued up
+*   on the freeChannelQ until a channel becomes available.
+*
+*****************************************************************************/
+
+typedef struct {
+       struct semaphore lock;  /* acquired when manipulating table entries */
+       wait_queue_head_t freeChannelQ;
+
+       DMA_Controller_t controller[DMA_NUM_CONTROLLERS];
+
+} DMA_Global_t;
+
+/* ---- Variable Externs ------------------------------------------------- */
+
+extern DMA_DeviceAttribute_t DMA_gDeviceAttribute[DMA_NUM_DEVICE_ENTRIES];
+
+/* ---- Function Prototypes ---------------------------------------------- */
+
+#if defined(__KERNEL__)
+
+/****************************************************************************/
+/**
+*   Initializes the DMA module.
+*
+*   @return
+*       0       - Success
+*       < 0     - Error
+*/
+/****************************************************************************/
+
+int dma_init(void);
+
+#if (DMA_DEBUG_TRACK_RESERVATION)
+DMA_Handle_t dma_request_channel_dbg(DMA_Device_t dev, const char *fileName,
+                                    int lineNum);
+#define dma_request_channel(dev)  dma_request_channel_dbg(dev, __FILE__, __LINE__)
+#else
+
+/****************************************************************************/
+/**
+*   Reserves a channel for use with @a dev. If the device is setup to use
+*   a shared channel, then this function will block until a free channel
+*   becomes available.
+*
+*   @return
+*       >= 0    - A valid DMA Handle.
+*       -EBUSY  - Device is currently being used.
+*       -ENODEV - Device handed in is invalid.
+*/
+/****************************************************************************/
+
+DMA_Handle_t dma_request_channel(DMA_Device_t dev      /* Device to use with the allocated channel. */
+    );
+#endif
+
+/****************************************************************************/
+/**
+*   Frees a previously allocated DMA Handle.
+*
+*   @return
+*        0      - DMA Handle was released successfully.
+*       -EINVAL - Invalid DMA handle
+*/
+/****************************************************************************/
+
+int dma_free_channel(DMA_Handle_t channel      /* DMA handle. */
+    );
+
+/****************************************************************************/
+/**
+*   Determines if a given device has been configured as using a shared
+*   channel.
+*
+*   @return boolean
+*       0           Device uses a dedicated channel
+*       non-zero    Device uses a shared channel
+*/
+/****************************************************************************/
+
+int dma_device_is_channel_shared(DMA_Device_t dev      /* Device to check. */
+    );
+
+/****************************************************************************/
+/**
+*   Allocates memory to hold a descriptor ring. The descriptor ring then
+*   needs to be populated by making one or more calls to
+*   dna_add_descriptors.
+*
+*   The returned descriptor ring will be automatically initialized.
+*
+*   @return
+*       0           Descriptor ring was allocated successfully
+*       -ENOMEM     Unable to allocate memory for the desired number of descriptors.
+*/
+/****************************************************************************/
+
+int dma_alloc_descriptor_ring(DMA_DescriptorRing_t *ring,      /* Descriptor ring to populate */
+                             int numDescriptors        /* Number of descriptors that need to be allocated. */
+    );
+
+/****************************************************************************/
+/**
+*   Releases the memory which was previously allocated for a descriptor ring.
+*/
+/****************************************************************************/
+
+void dma_free_descriptor_ring(DMA_DescriptorRing_t *ring       /* Descriptor to release */
+    );
+
+/****************************************************************************/
+/**
+*   Initializes a descriptor ring, so that descriptors can be added to it.
+*   Once a descriptor ring has been allocated, it may be reinitialized for
+*   use with additional/different regions of memory.
+*
+*   Note that if 7 descriptors are allocated, it's perfectly acceptable to
+*   initialize the ring with a smaller number of descriptors. The amount
+*   of memory allocated for the descriptor ring will not be reduced, and
+*   the descriptor ring may be reinitialized later
+*
+*   @return
+*       0           Descriptor ring was initialized successfully
+*       -ENOMEM     The descriptor which was passed in has insufficient space
+*                   to hold the desired number of descriptors.
+*/
+/****************************************************************************/
+
+int dma_init_descriptor_ring(DMA_DescriptorRing_t *ring,       /* Descriptor ring to initialize */
+                            int numDescriptors /* Number of descriptors to initialize. */
+    );
+
+/****************************************************************************/
+/**
+*   Determines the number of descriptors which would be required for a
+*   transfer of the indicated memory region.
+*
+*   This function also needs to know which DMA device this transfer will
+*   be destined for, so that the appropriate DMA configuration can be retrieved.
+*   DMA parameters such as transfer width, and whether this is a memory-to-memory
+*   or memory-to-peripheral, etc can all affect the actual number of descriptors
+*   required.
+*
+*   @return
+*       > 0     Returns the number of descriptors required for the indicated transfer
+*       -EINVAL Invalid device type for this kind of transfer
+*               (i.e. the device is _MEM_TO_DEV and not _DEV_TO_MEM)
+*       -ENOMEM Memory exhausted
+*/
+/****************************************************************************/
+
+int dma_calculate_descriptor_count(DMA_Device_t device,        /* DMA Device that this will be associated with */
+                                  dma_addr_t srcData,  /* Place to get data to write to device */
+                                  dma_addr_t dstData,  /* Pointer to device data address */
+                                  size_t numBytes      /* Number of bytes to transfer to the device */
+    );
+
+/****************************************************************************/
+/**
+*   Adds a region of memory to the descriptor ring. Note that it may take
+*   multiple descriptors for each region of memory. It is the callers
+*   responsibility to allocate a sufficiently large descriptor ring.
+*
+*   @return
+*       0       Descriptors were added successfully
+*       -EINVAL Invalid device type for this kind of transfer
+*               (i.e. the device is _MEM_TO_DEV and not _DEV_TO_MEM)
+*       -ENOMEM Memory exhausted
+*/
+/****************************************************************************/
+
+int dma_add_descriptors(DMA_DescriptorRing_t *ring,    /* Descriptor ring to add descriptors to */
+                       DMA_Device_t device,    /* DMA Device that descriptors are for */
+                       dma_addr_t srcData,     /* Place to get data (memory or device) */
+                       dma_addr_t dstData,     /* Place to put data (memory or device) */
+                       size_t numBytes /* Number of bytes to transfer to the device */
+    );
+
+/****************************************************************************/
+/**
+*   Sets the descriptor ring associated with a device.
+*
+*   Once set, the descriptor ring will be associated with the device, even
+*   across channel request/free calls. Passing in a NULL descriptor ring
+*   will release any descriptor ring currently associated with the device.
+*
+*   Note: If you call dma_transfer, or one of the other dma_alloc_ functions
+*         the descriptor ring may be released and reallocated.
+*
+*   Note: This function will release the descriptor memory for any current
+*         descriptor ring associated with this device.
+*/
+/****************************************************************************/
+
+int dma_set_device_descriptor_ring(DMA_Device_t device,        /* Device to update the descriptor ring for. */
+                                  DMA_DescriptorRing_t *ring   /* Descriptor ring to add descriptors to */
+    );
+
+/****************************************************************************/
+/**
+*   Retrieves the descriptor ring associated with a device.
+*/
+/****************************************************************************/
+
+int dma_get_device_descriptor_ring(DMA_Device_t device,        /* Device to retrieve the descriptor ring for. */
+                                  DMA_DescriptorRing_t *ring   /* Place to store retrieved ring */
+    );
+
+/****************************************************************************/
+/**
+*   Allocates buffers for the descriptors. This is normally done automatically
+*   but needs to be done explicitly when initiating a dma from interrupt
+*   context.
+*
+*   @return
+*       0       Descriptors were allocated successfully
+*       -EINVAL Invalid device type for this kind of transfer
+*               (i.e. the device is _MEM_TO_DEV and not _DEV_TO_MEM)
+*       -ENOMEM Memory exhausted
+*/
+/****************************************************************************/
+
+int dma_alloc_descriptors(DMA_Handle_t handle, /* DMA Handle */
+                         dmacHw_TRANSFER_TYPE_e transferType,  /* Type of transfer being performed */
+                         dma_addr_t srcData,   /* Place to get data to write to device */
+                         dma_addr_t dstData,   /* Pointer to device data address */
+                         size_t numBytes       /* Number of bytes to transfer to the device */
+    );
+
+/****************************************************************************/
+/**
+*   Allocates and sets up descriptors for a double buffered circular buffer.
+*
+*   This is primarily intended to be used for things like the ingress samples
+*   from a microphone.
+*
+*   @return
+*       > 0     Number of descriptors actually allocated.
+*       -EINVAL Invalid device type for this kind of transfer
+*               (i.e. the device is _MEM_TO_DEV and not _DEV_TO_MEM)
+*       -ENOMEM Memory exhausted
+*/
+/****************************************************************************/
+
+int dma_alloc_double_dst_descriptors(DMA_Handle_t handle,      /* DMA Handle */
+                                    dma_addr_t srcData,        /* Physical address of source data */
+                                    dma_addr_t dstData1,       /* Physical address of first destination buffer */
+                                    dma_addr_t dstData2,       /* Physical address of second destination buffer */
+                                    size_t numBytes    /* Number of bytes in each destination buffer */
+    );
+
+/****************************************************************************/
+/**
+*   Initializes a DMA_MemMap_t data structure
+*/
+/****************************************************************************/
+
+int dma_init_mem_map(DMA_MemMap_t *memMap      /* Stores state information about the map */
+    );
+
+/****************************************************************************/
+/**
+*   Releases any memory currently being held by a memory mapping structure.
+*/
+/****************************************************************************/
+
+int dma_term_mem_map(DMA_MemMap_t *memMap      /* Stores state information about the map */
+    );
+
+/****************************************************************************/
+/**
+*   Looks at a memory address and categorizes it.
+*
+*   @return One of the values from the DMA_MemType_t enumeration.
+*/
+/****************************************************************************/
+
+DMA_MemType_t dma_mem_type(void *addr);
+
+/****************************************************************************/
+/**
+*   Sets the process (aka userTask) associated with a mem map. This is
+*   required if user-mode segments will be added to the mapping.
+*/
+/****************************************************************************/
+
+static inline void dma_mem_map_set_user_task(DMA_MemMap_t *memMap,
+                                            struct task_struct *task)
+{
+       memMap->userTask = task;
+}
+
+/****************************************************************************/
+/**
+*   Looks at a memory address and determines if we support DMA'ing to/from
+*   that type of memory.
+*
+*   @return boolean -
+*               return value != 0 means dma supported
+*               return value == 0 means dma not supported
+*/
+/****************************************************************************/
+
+int dma_mem_supports_dma(void *addr);
+
+/****************************************************************************/
+/**
+*   Initializes a memory map for use. Since this function acquires a
+*   sempaphore within the memory map, it is VERY important that dma_unmap
+*   be called when you're finished using the map.
+*/
+/****************************************************************************/
+
+int dma_map_start(DMA_MemMap_t *memMap,        /* Stores state information about the map */
+                 enum dma_data_direction dir   /* Direction that the mapping will be going */
+    );
+
+/****************************************************************************/
+/**
+*   Adds a segment of memory to a memory map.
+*
+*   @return     0 on success, error code otherwise.
+*/
+/****************************************************************************/
+
+int dma_map_add_region(DMA_MemMap_t *memMap,   /* Stores state information about the map */
+                      void *mem,       /* Virtual address that we want to get a map of */
+                      size_t numBytes  /* Number of bytes being mapped */
+    );
+
+/****************************************************************************/
+/**
+*   Creates a descriptor ring from a memory mapping.
+*
+*   @return 0 on sucess, error code otherwise.
+*/
+/****************************************************************************/
+
+int dma_map_create_descriptor_ring(DMA_Device_t dev,   /* DMA device (where the ring is stored) */
+                                  DMA_MemMap_t *memMap,        /* Memory map that will be used */
+                                  dma_addr_t devPhysAddr       /* Physical address of device */
+    );
+
+/****************************************************************************/
+/**
+*   Maps in a memory region such that it can be used for performing a DMA.
+*
+*   @return
+*/
+/****************************************************************************/
+
+int dma_map_mem(DMA_MemMap_t *memMap,  /* Stores state information about the map */
+               void *addr,     /* Virtual address that we want to get a map of */
+               size_t count,   /* Number of bytes being mapped */
+               enum dma_data_direction dir     /* Direction that the mapping will be going */
+    );
+
+/****************************************************************************/
+/**
+*   Maps in a memory region such that it can be used for performing a DMA.
+*
+*   @return
+*/
+/****************************************************************************/
+
+int dma_unmap(DMA_MemMap_t *memMap,    /* Stores state information about the map */
+             int dirtied       /* non-zero if any of the pages were modified */
+    );
+
+/****************************************************************************/
+/**
+*   Initiates a transfer when the descriptors have already been setup.
+*
+*   This is a special case, and normally, the dma_transfer_xxx functions should
+*   be used.
+*
+*   @return
+*       0       Transfer was started successfully
+*       -ENODEV Invalid handle
+*/
+/****************************************************************************/
+
+int dma_start_transfer(DMA_Handle_t handle);
+
+/****************************************************************************/
+/**
+*   Stops a previously started DMA transfer.
+*
+*   @return
+*       0       Transfer was stopped successfully
+*       -ENODEV Invalid handle
+*/
+/****************************************************************************/
+
+int dma_stop_transfer(DMA_Handle_t handle);
+
+/****************************************************************************/
+/**
+*   Waits for a DMA to complete by polling. This function is only intended
+*   to be used for testing. Interrupts should be used for most DMA operations.
+*/
+/****************************************************************************/
+
+int dma_wait_transfer_done(DMA_Handle_t handle);
+
+/****************************************************************************/
+/**
+*   Initiates a DMA transfer
+*
+*   @return
+*       0       Transfer was started successfully
+*       -EINVAL Invalid device type for this kind of transfer
+*               (i.e. the device is _MEM_TO_DEV and not _DEV_TO_MEM)
+*/
+/****************************************************************************/
+
+int dma_transfer(DMA_Handle_t handle,  /* DMA Handle */
+                dmacHw_TRANSFER_TYPE_e transferType,   /* Type of transfer being performed */
+                dma_addr_t srcData,    /* Place to get data to write to device */
+                dma_addr_t dstData,    /* Pointer to device data address */
+                size_t numBytes        /* Number of bytes to transfer to the device */
+    );
+
+/****************************************************************************/
+/**
+*   Initiates a transfer from memory to a device.
+*
+*   @return
+*       0       Transfer was started successfully
+*       -EINVAL Invalid device type for this kind of transfer
+*               (i.e. the device is _DEV_TO_MEM and not _MEM_TO_DEV)
+*/
+/****************************************************************************/
+
+static inline int dma_transfer_to_device(DMA_Handle_t handle,  /* DMA Handle */
+                                        dma_addr_t srcData,    /* Place to get data to write to device (physical address) */
+                                        dma_addr_t dstData,    /* Pointer to device data address (physical address) */
+                                        size_t numBytes        /* Number of bytes to transfer to the device */
+    ) {
+       return dma_transfer(handle,
+                           dmacHw_TRANSFER_TYPE_MEM_TO_PERIPHERAL,
+                           srcData, dstData, numBytes);
+}
+
+/****************************************************************************/
+/**
+*   Initiates a transfer from a device to memory.
+*
+*   @return
+*       0       Transfer was started successfully
+*       -EINVAL Invalid device type for this kind of transfer
+*               (i.e. the device is _MEM_TO_DEV and not _DEV_TO_MEM)
+*/
+/****************************************************************************/
+
+static inline int dma_transfer_from_device(DMA_Handle_t handle,        /* DMA Handle */
+                                          dma_addr_t srcData,  /* Pointer to the device data address (physical address) */
+                                          dma_addr_t dstData,  /* Place to store data retrieved from the device (physical address) */
+                                          size_t numBytes      /* Number of bytes to retrieve from the device */
+    ) {
+       return dma_transfer(handle,
+                           dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM,
+                           srcData, dstData, numBytes);
+}
+
+/****************************************************************************/
+/**
+*   Initiates a memory to memory transfer.
+*
+*   @return
+*       0       Transfer was started successfully
+*       -EINVAL Invalid device type for this kind of transfer
+*               (i.e. the device wasn't DMA_DEVICE_MEM_TO_MEM)
+*/
+/****************************************************************************/
+
+static inline int dma_transfer_mem_to_mem(DMA_Handle_t handle, /* DMA Handle */
+                                         dma_addr_t srcData,   /* Place to transfer data from (physical address) */
+                                         dma_addr_t dstData,   /* Place to transfer data to (physical address) */
+                                         size_t numBytes       /* Number of bytes to transfer */
+    ) {
+       return dma_transfer(handle,
+                           dmacHw_TRANSFER_TYPE_MEM_TO_MEM,
+                           srcData, dstData, numBytes);
+}
+
+/****************************************************************************/
+/**
+*   Set the callback function which will be called when a transfer completes.
+*   If a NULL callback function is set, then no callback will occur.
+*
+*   @note   @a devHandler will be called from IRQ context.
+*
+*   @return
+*       0       - Success
+*       -ENODEV - Device handed in is invalid.
+*/
+/****************************************************************************/
+
+int dma_set_device_handler(DMA_Device_t dev,   /* Device to set the callback for. */
+                          DMA_DeviceHandler_t devHandler,      /* Function to call when the DMA completes */
+                          void *userData       /* Pointer which will be passed to devHandler. */
+    );
+
+#endif
+
+#endif /* ASM_ARM_ARCH_BCMRING_DMA_H */