summaryrefslogtreecommitdiff
path: root/ANDROID_3.4.5/arch/arm/mach-wmt/dma.c
diff options
context:
space:
mode:
Diffstat (limited to 'ANDROID_3.4.5/arch/arm/mach-wmt/dma.c')
-rwxr-xr-xANDROID_3.4.5/arch/arm/mach-wmt/dma.c1361
1 files changed, 0 insertions, 1361 deletions
diff --git a/ANDROID_3.4.5/arch/arm/mach-wmt/dma.c b/ANDROID_3.4.5/arch/arm/mach-wmt/dma.c
deleted file mode 100755
index ad6db63d..00000000
--- a/ANDROID_3.4.5/arch/arm/mach-wmt/dma.c
+++ /dev/null
@@ -1,1361 +0,0 @@
-/*++
- arch/arm/mach-wmt/dma.c - DMA 5 driver
-
- Copyright (c) 2013 WonderMedia Technologies, Inc.
-
- This program is free software: you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software Foundation,
- either version 2 of the License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
- PARTICULAR PURPOSE. See the GNU General Public License for more details.
- You should have received a copy of the GNU General Public License along with
- this program. If not, see <http://www.gnu.org/licenses/>.
-
- WonderMedia Technologies, Inc.
- 10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C.
---*/
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/sched.h>
-#include <linux/spinlock.h>
-#include <linux/errno.h>
-#include <linux/proc_fs.h>
-#include <linux/syscore_ops.h>
-
-#include <linux/pm.h>
-#include <linux/delay.h>
-
-#include <asm/system.h>
-#include <asm/irq.h>
-#include <mach/hardware.h>
-#include <asm/dma.h>
-#include <asm/io.h>
-#include <linux/dma-mapping.h>
-#include <mach/dma.h>
-
-#undef DMA4_ERRATA
-#undef DEBUG
-/*#define DEBUG*/
-
-#ifdef DEBUG
-#define DPRINTK(fmt, args...) printk("%s: " fmt, __func__ , ## args)
-#else
-#define DPRINTK(x...)
-#endif
-
-#define MAX_DESCRIPT_SIZE SIZE_1KB
-
-int revise_descript( dmach_t ch, struct dma_device_cfg_s device_cfg, struct dma_mem_reg_group_s dma_mem_reg);
-
-extern unsigned int wmt_read_oscr(void);
-
-/*-----------------------------------------------------------------------------*/
-/* DMA channel structure.*/
-/*-----------------------------------------------------------------------------*/
-struct dma_info_s {
- dmach_t channel_no ; /* channel no*/
- struct dma_regs_s *regs; /* points to appropriate DMA registers*/
- int irq; /* IRQ Index used by the channel*/
- const char *device_id; /* device name*/
- void (*callback)(void *data); /* to call when buffers are done*/
- void *callback_data; /* with private data ptr*/
- enum dma_device_e device_no ; /* device no*/
- struct dma_device_cfg_s device_cfg ; /* device cfg*/
- int in_use; /* Does someone own the channel*/
- int des0cnt; /* descript 0 current index*/
- int des1cnt; /*descript 1 current index*/
- int max_des0cnt; /*the largest descript 0 number*/
- int max_des1cnt; /*the largest descript 1 number*/
- int residue_des0cnt ; /*residue descript 0 count need to be xfer*/
- int residue_des1cnt ; /*residue descript 1 count need to be xfer*/
- struct dma_descript_addr des_addr;
- dma_addr_t des0_phy_addr ;
- dma_addr_t des1_phy_addr ;
- unsigned int accu_size; /*accumlate size between the dma interrupt*/
- unsigned int descript_size; /*the max descript size*/
-
-} ;
-
-struct dma_int_s {
- unsigned int request_chans ;
- struct dma_regs_s *regs;
-
-};
-
-struct des_attribute {
- unsigned int end_descript;
- unsigned int interrupt_en;
- unsigned int size;
- unsigned int fmt;
- dma_addr_t data_addr;
- dma_addr_t branch_addr;
-};
-
-
-/*-----------------------------------------------------------------------------*/
-/* variable*/
-/*-----------------------------------------------------------------------------*/
-static struct dma_int_s dma_int ;
-
-static struct dma_info_s dma_chan[MAX_DMA_CHANNELS];
-
-static struct dma_mem_reg_s *dma_mem_regs;
-
-static dma_addr_t dma_mem_phy;
-
-/* static spinlock_t dma_list_lock = SPIN_LOCK_UNLOCKED;*/
-static DEFINE_SPINLOCK(dma_list_lock);
-
-static unsigned int dma_irq_no[] = {
- IRQ_DMA_NONS,
- IRQ_DMA_NONS,
- IRQ_DMA_NONS,
- IRQ_DMA_NONS,
- IRQ_DMA_NONS,
- IRQ_DMA_NONS,
- IRQ_DMA_NONS,
- IRQ_DMA_NONS,
- IRQ_DMA_NONS,
- IRQ_DMA_NONS,
- IRQ_DMA_NONS,
- IRQ_DMA_NONS,
- IRQ_DMA_NONS,
- IRQ_DMA_NONS,
- IRQ_DMA_NONS,
- IRQ_DMA_NONS,
-};
-
-struct dma_device_cfg_s dma_device_cfg_table[] = {
- /* DeviceReq , DefaultCCR , Source_0, Destination_0 */
- { SPI0_DMA_TX_REQ , 0x00000100 , 0, 0 , SIZE_4KB}, /*spi0*/
- { SPI0_DMA_RX_REQ , 0x00000100 , 0, 0 , SIZE_4KB}, /*spi1*/
- { SPI1_DMA_TX_REQ , 0x00000100 , 0, 0 , SIZE_4KB},
- { SPI1_DMA_RX_REQ , 0x00000100 , 0, 0 , SIZE_4KB},
- { PCM1_TX_DMA_REQ , 0x00000100, 0, 0 , SIZE_4KB},
- { PCM1_RX_DMA_REQ , 0x00000100, 0, 0 , SIZE_4KB},
- /* start from 0, above 5, below 6 */
- { UART_0_TX_DMA_REQ , UART_TX_DMA_CFG, 0, UART0_TX_FIFO , SIZE_1B}, /*uart0*/
- { UART_0_RX_DMA_REQ , UART_RX_DMA_CFG, 0, UART0_RX_FIFO , SIZE_4KB}, /*uart0*/
- { UART_1_TX_DMA_REQ , UART_TX_DMA_CFG, 0, UART1_TX_FIFO , SIZE_1B}, /*uart1*/
- { UART_1_RX_DMA_REQ , UART_RX_DMA_CFG, 0, UART1_RX_FIFO , SIZE_4KB}, /*uart1*/
- { UART_2_TX_DMA_REQ , UART_TX_DMA_CFG, 0, UART2_TX_FIFO , SIZE_1B}, /*uart2*/
- /*start from 0, above 10, below 11 */
- { UART_2_RX_DMA_REQ , UART_RX_DMA_CFG, 0, UART2_RX_FIFO , SIZE_4KB}, /*uart2*/
- { UART_3_TX_DMA_REQ , UART_TX_DMA_CFG, 0, UART3_TX_FIFO , SIZE_1B}, /*uart3*/
- { UART_3_RX_DMA_REQ , UART_RX_DMA_CFG, 0, UART3_RX_FIFO , SIZE_4KB}, /*uart3*/
- { PCM_TX_DMA_REQ, PCM_TX_DMA_CFG, 0, PCM_TX_FIFO, SIZE_4KB},
- { PCM_RX_DMA_REQ, PCM_RX_DMA_CFG, 0, PCM_RX_FIFO, SIZE_4KB},
- /*start from 0, above 15, below 16 */
- { DEVICE_RESERVED , 0x00000100, 0, 0 , SIZE_4KB},
- { DEVICE_RESERVED , 0x00000100, 0, 0 , SIZE_4KB},
- { DEVICE_RESERVED , 0x00000100, 0, 0 , SIZE_4KB},
- { DEVICE_RESERVED , 0x00000100, 0, 0 , SIZE_4KB},
- { DEVICE_RESERVED , 0x00000100, 0, 0 , SIZE_4KB},
- /*start from 0, above 20, below 21 */
- { AHB1_AUD_DMA_REQ_0 , I2S_RX_DMA_CFG, 0, I2S_RX_FIFO , SIZE_16KB},
- { AHB1_AUD_DMA_REQ_1 , I2S_TX_DMA_CFG, 0, I2S_TX_FIFO , SIZE_16KB},
- { AHB1_AUD_DMA_REQ_2 , I2S_RX_DMA_CFG, 0, SPDIF_RX_FIFO, SIZE_16KB},
- { AHB1_AUD_DMA_REQ_3 , 0x00000100, 0, 0 , SIZE_4KB},
- { AHB1_AUD_DMA_REQ_4 , 0x00000100, 0, 0 , SIZE_4KB},
- { AHB1_AUD_DMA_REQ_5 , 0x00000100, 0, 0 , SIZE_4KB},
- { AHB1_AUD_DMA_REQ_6 , 0x00000100, 0, 0 , SIZE_4KB},
- { AHB1_AUD_DMA_REQ_7 , 0x00000100, 0, 0 , SIZE_4KB},
- { DEVICE_RESERVED , 0x00000100, 0, 0 , SIZE_4KB},
- { DEVICE_RESERVED , 0x00000100, 0, 0 , SIZE_4KB},
- /*start from 0, above 30, below 31 */
- { DEVICE_RESERVED , 0x00000100, 0, 0 , SIZE_4KB},
- { MEMORY_DMA_REQ , 0x2a800000, 0x0a200000 , 0x0a220000 , SIZE_4KB},
- { DEVICE_RESERVED , 0x00000100, 0, 0 , SIZE_4KB},
-};
-EXPORT_SYMBOL(dma_device_cfg_table);
-
-/*===========================================================================*/
-/* dma_irq_handler*/
-/**/
-/* return: 0*/
-/*===========================================================================*/
-static irqreturn_t
-dma_irq_handler(int irq, void *dev_id)
-{
- int ch ;
- unsigned int global_st ;
- unsigned char channel_st ;
- struct dma_info_s *dma = NULL ;
- struct dma_mem_reg_group_s dma_mem_reg ;
-
- global_st = dma_int.regs->DMA_ISR & 0xFFFF ;
-
- for (ch = 0 ; ch < MAX_DMA_CHANNELS ; ++ch) {
- if (global_st & 1 << ch) {
- channel_st = dma_int.regs->DMA_CCR_CH[ch] & DMA_EVT_ID_MASK;
- break ;
- }
- }
- DPRINTK("%s :dma ch = %d\n", __func__, ch);
-
-
- if (ch >= MAX_DMA_CHANNELS) {
- printk(KERN_ERR "DMA : unknown DMA IRQ\n\r") ;
- return IRQ_HANDLED ;
- }
- /*
- * ch active handling
- */
- dma = &dma_chan[ch] ;
- dma_int.regs->DMA_ISR = 1 << ch ;
- /*
- * Handle channel DMA error
- */
- if ((channel_st == DMA_EVT_NO_STATUS)) {
- /*
- * DMA request finished with no error
- * Vincent 2009/05/19
- */
- dma_mem_reg = wmt_get_dma_pos_info(ch);
- revise_descript(ch, dma->device_cfg, dma_mem_reg);
- } else if ((channel_st != DMA_EVT_SUCCESS) && (channel_st != DMA_EVT_NO_STATUS)) {
- /* 1. clear error/abort status*/
- /* 2. re-program src/des/cnt reg 0 and 1*/
- /* 3. write "1" to csr bit6 to reset the buffer pointer to 0*/
- /* 4. re-enable dma channle*/
- printk(KERN_ERR "ch=%d status=0x%.2x err\n\r",
- ch, channel_st) ;
- /*
- * dma->callback(dma->callback_data) ;
- * if callback runs, audio driver think this descp is done
- * Vincent 2009/05/19
- */
- wmt_resume_dma(ch);
- /* free buffer and callback to handle error*/
- return IRQ_HANDLED ;
- }
- /*
- * Decrease the channel descript usage indicator.
- */
- if (dma->residue_des0cnt > 0)
- --dma->residue_des0cnt;
- if (dma->callback)
- dma->callback(dma->callback_data) ;
-
- return IRQ_HANDLED;
-}
-
-int create_fmt0_descript(
- dmach_t ch,
- struct dma_device_cfg_s device_cfg,
- struct des_attribute descript_attr)
-{
- struct dma_info_s *dma ;
- struct dma_des_fmt0 descript;
- unsigned int ReqCnt = 0;
- unsigned int des_offset;
- descript.DataAddr = 0;
- descript.ReqCnt = 0;
- dma = &dma_chan[ch] ;
- des_offset = dma->des0cnt * sizeof(struct dma_des_fmt0)/sizeof(unsigned long);
-
- DPRINTK("[%s] : create fmt 0 descript size=%x\n", __func__, descript_attr.size);
- DPRINTK("[%s] : des0cnt = %x\n", __func__, dma->des0cnt);
-
- if ((ch >= MAX_DMA_CHANNELS) || (dma_chan[ch].in_use == 0)) {
- printk("%s: bad DMA identifier\n", __func__) ;
- return -EINVAL ;
- }
-
- if (dma->device_no != device_cfg.DeviceReqType) {
- printk("%s: bad Device_NO\n", __func__) ;
- return -ENODEV ;
- }
-
- descript.DataAddr = (unsigned long)descript_attr.data_addr;
- if (descript_attr.interrupt_en == 1)
- ReqCnt |= DMA_INTEN_DES;
- if (descript_attr.end_descript == 1)
- ReqCnt |= DMA_DES_END;
- if (descript_attr.size > (SIZE_64KB - 1))
- return -EOVERFLOW ;
- descript.ReqCnt = ReqCnt | descript_attr.size;
- DPRINTK("[%s]:des_offset = %d , des0 = 0x%x\n",
- __func__, des_offset, dma->des_addr.des_0 + des_offset);
- *(dma->des_addr.des_0 + des_offset) = descript.ReqCnt;
- *(dma->des_addr.des_0 + des_offset + 1) = descript.DataAddr;
- ++dma->des0cnt;
- return 0;
-
-}
-
-int create_fmt1_descript(
- dmach_t ch,
- struct dma_device_cfg_s device_cfg,
- struct des_attribute descript_attr)
-{
- struct dma_info_s *dma ;
- struct dma_des_fmt1 descript;
- unsigned int ReqCnt = 0;
- unsigned int des_offset;
- descript.DataAddr = 0;
- descript.ReqCnt = 0;
- dma = &dma_chan[ch] ;
- des_offset = (dma->max_des0cnt - 1) * sizeof(struct dma_des_fmt0) / sizeof(unsigned long);
-
- DPRINTK("[%s]:create fmt 1 descript size=%x\n", __func__, descript_attr.size);
- DPRINTK("[%s]:des0cnt = %x\n", __func__, dma->des0cnt);
- DPRINTK("[%s]:branch_addr = %x\n", __func__, descript_attr.branch_addr);
-
- if ((ch >= MAX_DMA_CHANNELS) || (dma_chan[ch].in_use == 0)) {
- printk("%s: bad DMA identifier\n", __func__) ;
- return -EINVAL ;
- }
-
- if (dma->device_no != device_cfg.DeviceReqType) {
- printk("%s: bad Device_NO\n", __func__) ;
- return -ENODEV ;
- }
- /*if (descript_attr.size > (SIZE_64KB - 1))*/
- descript.DataAddr = (unsigned long)descript_attr.data_addr;
- descript.BrAddr = (unsigned long)descript_attr.branch_addr;
- if (descript_attr.interrupt_en == 1)
- ReqCnt |= DMA_INTEN_DES;
- if (descript_attr.end_descript == 1)
- ReqCnt |= DMA_DES_END;
- if (descript_attr.fmt == 1)
- ReqCnt |= DMA_FORMAT_DES1;
- if (descript_attr.size > (SIZE_64KB - 1))
- return -EOVERFLOW ;
- DPRINTK("[%s] : fmt_1 des_offset = %d , des0 = 0x%x\n",
- __func__, des_offset, dma->des_addr.des_0 + des_offset);
- descript.ReqCnt = ReqCnt | descript_attr.size;
- *(dma->des_addr.des_0 + des_offset) = descript.ReqCnt;
- *(dma->des_addr.des_0 + des_offset + 1) = descript.DataAddr;
- *(dma->des_addr.des_0 + des_offset + 2) = descript.BrAddr ;
- dma->des0cnt = 0;
- return 0;
-}
-
-int clear_last_descript(
- dmach_t ch,
- struct dma_device_cfg_s device_cfg)
-{
- struct dma_info_s *dma ;
- unsigned int des_offset;
- dma = &dma_chan[ch] ;
-
- if ((dma->des0cnt - 1 >= 0))
- des_offset = (dma->des0cnt - 1) * sizeof(struct dma_des_fmt0) / sizeof(unsigned long);
- else
- des_offset = (dma->max_des0cnt - 1) * sizeof(struct dma_des_fmt0) / sizeof(unsigned long);
-
- if ((ch >= MAX_DMA_CHANNELS) || (dma_chan[ch].in_use == 0)) {
- printk("%s: bad DMA identifier\n", __func__) ;
- return -EINVAL ;
- }
-
- if (dma->device_no != device_cfg.DeviceReqType) {
- printk("%s: bad Device_NO\n", __func__) ;
- return -ENODEV ;
- }
- *(dma->des_addr.des_0 + des_offset) &= ~(DMA_DES_END);
- return 0;
-}
-int add_descript(
- dmach_t ch,
- struct dma_device_cfg_s device_cfg,
- dma_addr_t dma_ptr ,
- unsigned int size)
-{
- struct dma_info_s *dma ;
- unsigned int residue_size;
- unsigned int xfer_size;
- unsigned int xfer_index;
- unsigned int ret = 0;
- struct des_attribute descript_attr;
- int need_add_descript_count = 0;
- dma = &dma_chan[ch] ;
- residue_size = size;
- xfer_index = 0;
- need_add_descript_count = size/SIZE_32KB ;
- if (size%SIZE_32KB)
- ++need_add_descript_count;
- if ((ch >= MAX_DMA_CHANNELS) || (dma_chan[ch].in_use == 0)) {
- printk("%s: bad DMA identifier\n", __func__) ;
- return -EINVAL ;
- }
-
- if (dma->device_no != device_cfg.DeviceReqType) {
- printk("%s: bad Device_NO\n", __func__) ;
- return -ENODEV ;
- }
- if ((dma->max_des0cnt - dma->residue_des0cnt) < need_add_descript_count) {
- printk("%s:dma descripts are full\n",__func__);
- return -EBUSY ;
- }
- while (residue_size > 0) {
- if (residue_size == size)
- ret = clear_last_descript(ch, device_cfg);
-
- xfer_size = residue_size;
- if (residue_size > SIZE_32KB) {
- //xfer_size = residue_size - SIZE_32KB;
- xfer_size = SIZE_32KB;//vincent
- dma->accu_size += xfer_size;
- residue_size -= SIZE_32KB;
- dma_ptr += xfer_size * xfer_index;
- } else {
- xfer_size = residue_size;
- dma_ptr += xfer_size * xfer_index;
- dma->accu_size += xfer_size;
- residue_size = 0;
- }
-
- if (dma->des0cnt < dma->max_des0cnt - 1) {
- if (residue_size <= SIZE_32KB)
- descript_attr.end_descript = 1;
- if (dma->accu_size >= device_cfg.ChunkSize) {
- descript_attr.interrupt_en = 1;
- dma->accu_size = 0;
- dma->accu_size += xfer_size;
- }
- descript_attr.data_addr = dma_ptr;
- descript_attr.size = xfer_size ;
- descript_attr.fmt = 0;
- ret = create_fmt0_descript(ch,
- device_cfg,
- descript_attr);
- } else {
- if (residue_size <= SIZE_32KB)
- descript_attr.end_descript = 1;
- if (dma->accu_size >= device_cfg.ChunkSize) {
- descript_attr.interrupt_en = 1;
- dma->accu_size = 0;
- dma->accu_size += xfer_size;
- }
- descript_attr.data_addr = dma_ptr;
- descript_attr.branch_addr = dma->des0_phy_addr;
- descript_attr.size = xfer_size ;
- descript_attr.fmt = 1;
- ret = create_fmt1_descript(ch,
- device_cfg,
- descript_attr);
- }
- xfer_index++;
- }
- return xfer_index;
-}
-
-int revise_descript(
- dmach_t ch,
- struct dma_device_cfg_s device_cfg,
- struct dma_mem_reg_group_s dma_mem_reg)
-{
- struct dma_info_s *dma ;
- unsigned int ret = 0;
- unsigned int des_offset = 0;
- unsigned int req_count = 0;
- unsigned int data_address = 0;
-#ifdef DMA4_ERRATA
- unsigned long flags;
- unsigned int now_time = 0;
- unsigned int delay_time = 0;
-#endif
- dma = &dma_chan[ch] ;
- if ((ch >= MAX_DMA_CHANNELS) || (dma_chan[ch].in_use == 0)) {
- printk("%s: bad DMA identifier\n", __func__) ;
- return -EINVAL ;
- }
-
- if (dma->device_no != device_cfg.DeviceReqType) {
- printk("%s: bad Device_NO\n", __func__) ;
- return -ENODEV ;
- }
-#ifdef DMA4ERRATA
- if (dma->regs->DMA_CCR_CH[ch] & (SYSTEM_DMA_RUN)) {
- spin_lock_irqsave(&dma_list_lock, flags);
- dma->regs->DMA_CCR_CH[ch] |= (DMA_UP_MEMREG_EN);/*update memory register before reading*/
- now_time = wmt_read_oscr();
- while (dma->regs->DMA_CCR_CH[ch] & (DMA_UP_MEMREG_EN)) {
- delay_time = wmt_read_oscr() - now_time;
- if (delay_time > 15) {/*5us*/
- DPRINTK("[%d]Warnning:up_mem_reg did not clear[%x]\n", ch, dma->regs->DMA_CCR_CH[ch]);
- dma->regs->DMA_CCR_CH[ch] &= ~DMA_UP_MEMREG_EN;/*clear DMA_UP_MEMREG_EN*/
- break;
- }
-
- }
- spin_unlock_irqrestore(&dma_list_lock, flags);
- }
-#endif
- req_count = dma_mem_reg.DMA_IF0RBR_CH;
- req_count &= (DMA_DES_REQCNT_MASK) ;/*Vincent 2009.5.4*/
- data_address = dma_mem_reg.DMA_IF0DAR_CH;
- des_offset = dma_mem_reg.DMA_IF0CPR_CH - dma->des0_phy_addr ;
- if (req_count > 0) {
- *(dma->des_addr.des_0 + (des_offset / sizeof(unsigned long))) &= ~(DMA_DES_REQCNT_MASK);
- *(dma->des_addr.des_0 + (des_offset / sizeof(unsigned long))) |= req_count;
- *(dma->des_addr.des_0 + (des_offset / sizeof(unsigned long)) + 1) = 0;
- *(dma->des_addr.des_0 + (des_offset / sizeof(unsigned long)) + 1) = data_address;
- } else {
- /*Vincent 2009/05/19*/
- if (des_offset < (dma->max_des0cnt - 1) * DMA_DES0_SIZE)
- dma_mem_reg.DMA_IF0CPR_CH += 8;
- else
- dma_mem_reg.DMA_IF0CPR_CH = dma->des0_phy_addr;
-
- }
- return ret ;
-}
-/*=============================================================================*/
-/**/
-/* wmt_start_dma - submit a data buffer for DMA*/
-/* Memory To Device or Device To Memory*/
-/* @ch: identifier for the channel to use*/
-/* @dma_ptr: buffer physical (or bus) start address*/
-/* @dma_ptr2: device FIFO address*/
-/* @size: buffer size*/
-/**/
-/* Memory To Memory*/
-/* @ch: identifier for the channel to use*/
-/* @dma_ptr: buffer physical (or bus) source start address*/
-/* @dma_ptr2: buffer physical (or bus) destination start address*/
-/* @size: buffer size*/
-/**/
-/* This function hands the given data buffer to the hardware for DMA*/
-/* access. If another buffer is already in flight then this buffer*/
-/* will be queued so the DMA engine will switch to it automatically*/
-/* when the previous one is done. The DMA engine is actually toggling*/
-/* between two buffers so at most 2 successful calls can be made before*/
-/* one of them terminates and the callback function is called.*/
-/**/
-/* The @ch identifier is provided by a successful call to*/
-/* wmt_request_dma().*/
-/**/
-/* The @size must not be larger than %MAX_DMA_SIZE. If a given buffer*/
-/* is larger than that then it's the caller's responsibility to split*/
-/* it into smaller chunks and submit them separately. If this is the*/
-/* case then a @size of %CUT_DMA_SIZE is recommended to avoid ending*/
-/* up with too small chunks. The callback function can be used to chain*/
-/* submissions of buffer chunks.*/
-/**/
-/* Error return values:*/
-/* %-EOVERFLOW: Given buffer size is too big.*/
-/* %-EBUSY: Both DMA buffers are already in use.*/
-/* %-EAGAIN: Both buffers were busy but one of them just completed*/
-/* but the interrupt handler has to execute first.*/
-/**/
-/* This function returs 0 on success.*/
-/**/
-/*=============================================================================*/
-int wmt_start_dma(dmach_t ch, dma_addr_t dma_ptr, dma_addr_t dma_prt2, unsigned int size)
-{
- unsigned long flags;
- int count ;
- int ret = 0;
- int descript_count = 0;
- struct dma_info_s *dma = &dma_chan[ch] ;
- /*dump_dma_regs(ch);*/
-
- DPRINTK("size = %x, chunksize=%x\n", size, dma->device_cfg.ChunkSize);
-
- if (size == 0)
- return -EINVAL ;
-
- local_irq_save(flags);
-
- descript_count = add_descript(ch, dma->device_cfg, dma_ptr, size);
- if (descript_count < 0){
- ret = -EBUSY;
- goto start_dma_out;
- }
-
- dma->residue_des0cnt += descript_count ;
- if (dma->residue_des0cnt > dma->max_des0cnt - 1)
- {
- DPRINTK("%s: dma->residue_des0cnt(%d) is too large\n",
- __func__,dma->residue_des0cnt );
- dma->residue_des0cnt = dma->max_des0cnt - 1;
-
- }
- DPRINTK("%s: ch = %d, dma_ptr = 0x%8.8x, size = %d (0x%8.8X)\n",
- __func__, ch , dma_ptr, size , size);
-
- /* Calculate burst count*/
- if (dma->regs->DMA_CCR_CH[ch] & SYSTEM_DMA_RUN) {/*still run*/
- wmb();
- dma->regs->DMA_CCR_CH[ch] |= DMA_WAKE;
- wmb();
- } else {
- count = size ;
- dma_mem_regs->mem_reg_group[ch].DMA_IF0CPR_CH = dma->des0_phy_addr;
- DPRINTK("dma descript 0 phy addr = 0x%x\n", dma_mem_regs->mem_reg_group[ch].DMA_IF0CPR_CH);
- if (dma->device_cfg.DeviceReqType == MEMORY_DMA_REQ)
- dma_mem_regs->mem_reg_group[ch].DMA_IF1DAR_CH = dma->des0_phy_addr;
- wmb();
- dma->regs->DMA_CCR_CH[ch] |= (SYSTEM_DMA_RUN | SYSTEM_DMA_REQ_EN);
- wmb();
- }
-
-start_dma_out:
- local_irq_restore(flags);
- return ret ;
-}
-
-int wmt_wake_dma(
- dmach_t ch,
- dma_addr_t dma_ptr,
- dma_addr_t dma_prt2,
- unsigned int size)
-{
- int ret = 0;
- struct dma_info_s *dma = &dma_chan[ch] ;
- /*dump_dma_regs(ch);*/
-
- DPRINTK("size = %x, chunksize=%x\n", size, dma->device_cfg.ChunkSize);
-
- if (size == 0)
- return -EINVAL ;
- if (size > dma->device_cfg.ChunkSize)
- return -EOVERFLOW ;
- if (dma->regs->DMA_CCR_CH[ch] & SYSTEM_DMA_RUN) { /*still run*/
- ret = add_descript(ch, dma->device_cfg, dma_ptr, size);
- dma->residue_des0cnt += ret ;
- wmb();
- dma->regs->DMA_CCR_CH[ch] |= DMA_WAKE;
- wmb();
- }
- return ret ;
-}
-
-/*=============================================================================*/
-/**/
-/* wmt_request_dma - allocate one of the DMA chanels*/
-/* @channel: Pointer to the location of the allocated channel's identifier*/
-/* @device_id: An ascii name for the claiming device*/
-/* @device: The WMT peripheral targeted by this request*/
-/* @callback: Function to be called when the DMA completes*/
-/* @data: A cookie passed back to the callback function*/
-/**/
-/* This function will search for a free DMA channel and returns the*/
-/* address of the hardware registers for that channel as the channel*/
-/* identifier. This identifier is written to the location pointed by*/
-/* @dma_regs. The list of possible values for @device are listed into*/
-/* linux/include/asm-arm/arch-wmt/dma.h as a dma_device_t enum.*/
-/**/
-/* Note that reading from a port and writing to the same port are*/
-/* actually considered as two different streams requiring separate*/
-/* DMA registrations.*/
-/**/
-/* The @callback function is called from interrupt context when one*/
-/* of the two possible DMA buffers in flight has terminated. That*/
-/* function has to be small and efficient while posponing more complex*/
-/* processing to a lower priority execution context.*/
-/**/
-/* If no channels are available, or if the desired @device is already in*/
-/* use by another DMA channel, then an error code is returned. This*/
-/* function must be called before any other DMA calls.*/
-/**/
-/* return: 0 if successful*/
-/**/
-/*=============================================================================*/
-int wmt_request_dma(dmach_t *channel, const char *device_id, enum dma_device_e device,
- void (*callback)(void *data), void *callback_data)
-{
- int ch ;
- int descript_size = MAX_DESCRIPT_SIZE;
- struct dma_info_s *dma = NULL;
- *channel = -1;
-
- /* Ask for Free Channels*/
- spin_lock(&dma_list_lock);
- for (ch = 1 ; ch < MAX_DMA_CHANNELS ; ++ch) {
- dma = &dma_chan[ch];
- if (dma->in_use == 0)
- break ;
- }
- if (ch >= MAX_DMA_CHANNELS) {
- DPRINTK("DMA %s: no free DMA channel available\n", device_id);
- return -EBUSY;
- }
- spin_unlock(&dma_list_lock);
-
- dma_int.request_chans |= (1 << ch) ;
-
- /* Configure DMA channel settings.*/
- *channel = ch;
- dma->device_id = device_id;
- dma->device_no = device ;
- dma->callback = callback;
- dma->callback_data = callback_data ;
- dma->in_use = 1 ;
- dma->des0cnt = 0 ;
- dma->des1cnt = 0;
- dma->accu_size = 0;
- dma->residue_des0cnt = 0;
- dma->residue_des1cnt = 0;
- dma->descript_size = descript_size;
-
- /* clear status register*/
- dma->regs->DMA_ISR = 1 << ch;
- dma_mem_regs->mem_reg_group[ch].DMA_IF0CPR_CH = 0x0; /*reset descript*/
- dma_mem_regs->mem_reg_group[ch].DMA_IF1DAR_CH = 0x0; /*reset descript*/
- dma->des_addr.des_0 = (unsigned long *)dma_alloc_coherent(
- NULL,
- descript_size,
- &dma->des0_phy_addr,
- GFP_KERNEL);
- dma->max_des0cnt = (descript_size - DMA_DES1_SIZE) / DMA_DES0_SIZE + 1;
- DPRINTK("descript 0 addr--- virt:0x%x , phy:0x%x\n", dma->des_addr.des_0, dma->des0_phy_addr);
-
- /* setup default device*/
- dma->device_cfg = dma_device_cfg_table[device] ;
-
- dma->regs->DMA_CCR_CH[ch] = (dma_device_cfg_table[device].DefaultCCR & DMA_USER_SET_MASK) ;
-
- if (device != MEMORY_DMA_REQ)
- /*need to set device req number*/
- dma->regs->DMA_CCR_CH[ch] |= device << DMA_REQ_ID_SHIFT;
-
- else {
- dma->des_addr.des_1 = (unsigned long *)dma_alloc_coherent(NULL,
- descript_size, &dma->des0_phy_addr, GFP_KERNEL);
- dma->max_des1cnt = (descript_size - DMA_DES1_SIZE)/DMA_DES0_SIZE + 1;
- }
-
-
- DPRINTK("requested dma ch=%d to device=%d\n", ch, device);
-
- return 0 ; /* No error*/
-}
-
-/*=============================================================================*/
-/**/
-/* wmt_clear_dma - clear DMA pointers*/
-/* @ch:identifier for the channel to use*/
-/**/
-/* This clear any DMA state so the DMA engine is ready to restart*/
-/* with new buffers through wmt_start_dma(). Any buffers in flight*/
-/* are discarded.*/
-/**/
-/* The @regs identifier is provided by a successful call to*/
-/* wmt_request_dma().*/
-/**/
-/* return: NULL*/
-/*=============================================================================*/
-void wmt_clear_dma(dmach_t ch)
-{
- unsigned long flags;
- struct dma_info_s *dma ;
- dma = &dma_chan[ch] ;
-
- local_irq_save(flags);
-
- /* clear status register*/
- dma->regs->DMA_CCR_CH[ch] &= ~(SYSTEM_DMA_REQ_EN);
- udelay(5);
- dma->regs->DMA_CCR_CH[ch] &= ~(SYSTEM_DMA_RUN);
- dma->regs->DMA_ISR = 1 << ch; /*write 1 clear*/
- dma->des0cnt = 0;
- dma->des1cnt = 0;
- dma->accu_size = 0;
- dma->residue_des0cnt = 0;
- dma->residue_des0cnt = 0;
- local_irq_restore(flags);
-}
-
-/*=============================================================================*/
-/**/
-/* wmt_free_dma - free a WMT DMA channel*/
-/* @ch: identifier for the channel to free*/
-/**/
-/* This clears all activities on a given DMA channel and releases it*/
-/* for future requests. The @ch identifier is provided by a*/
-/* successful call to wmt_request_dma().*/
-/**/
-/* return: NULL*/
-/**/
-/*=============================================================================*/
-void wmt_free_dma(dmach_t ch)
-{
- struct dma_info_s *dma;
- enum dma_device_e dev_no ;
-
- if ((unsigned) ch >= MAX_DMA_CHANNELS) {
- DPRINTK("%s: bad DMA identifier\n", __func__);
- return ;
- }
-
- dma = &dma_chan[ch];
- if (dma->in_use == 0) {
- DPRINTK("%s: Trying to free DMA%d\n", __func__, ch);
- return;
- }
-
- if (dma->device_no == DEVICE_RESERVED) {
- DPRINTK("%s: Trying to free free DMA\n", __func__);
- return ;
- }
-
- wmt_clear_dma(ch);
-
- /* Int*/
- dma_int.request_chans &= ~(1 << ch) ;
-
- dev_no = dma->device_no ;
- dma_free_coherent(NULL,
- dma->descript_size,
- (void *)dma->des_addr.des_0,
- (dma_addr_t)dma->des0_phy_addr);
- if (dma->device_no == MEMORY_DMA_REQ)
- dma_free_coherent(NULL,
- dma->descript_size,
- (void *)dma->des_addr.des_1,
- (dma_addr_t)dma->des1_phy_addr);
-
- dma->device_no = DEVICE_RESERVED ;
- dma_chan[ch].device_id = NULL ;
- dma_chan[ch].des0cnt = 0;
- dma_chan[ch].des1cnt = 0;
- dma_chan[ch].accu_size = 0;
- dma_chan[ch].residue_des0cnt = 0;
- dma_chan[ch].residue_des0cnt = 0;
- dma_chan[ch].max_des0cnt = 0;
- dma_chan[ch].max_des1cnt = 0;
- dma_chan[ch].in_use = 0;
-}
-
-/*=============================================================================*/
-/**/
-/* wmt_reset_dma - reset a DMA channel*/
-/* @ch: identifier for the channel to use*/
-/**/
-/* This function resets and reconfigure the given DMA channel. This is*/
-/* particularly useful after a sleep/wakeup event.*/
-/**/
-/* The @ch identifier is provided by a successful call to*/
-/* request_dma().*/
-/**/
-/* return: NULL*/
-/**/
-/*=============================================================================*/
-void wmt_reset_dma(dmach_t ch)
-{
- if (ch >= MAX_DMA_CHANNELS) {
- DPRINTK("%s: bad DMA identifier\n", __func__);
- return;
- }
-
- wmt_clear_dma(ch);
-}
-
-/*===========================================================================*/
-/* wmt_setup_dma*/
-/**/
-/* Don't setup Dma channel while Dma is busy*/
-/**/
-/* return: 0: success*/
-/*===========================================================================*/
-int wmt_setup_dma(dmach_t ch, struct dma_device_cfg_s device_cfg)
-{
- struct dma_info_s *dma ;
- enum dma_device_e dev_no ;
-
- dma = &dma_chan[ch] ;
-
- if ((ch >= MAX_DMA_CHANNELS) || (dma_chan[ch].in_use == 0)) {
- printk("%s: bad DMA identifier\n", __func__) ;
- return -EINVAL ;
- }
-
- if (dma->device_no != device_cfg.DeviceReqType) {
- printk("%s: bad Device_NO\n", __func__) ;
- return -ENODEV ;
- }
-
- /* Apply new device config to DMA interface.*/
- dev_no = dma->device_no ;
- dma_device_cfg_table[dev_no] = device_cfg ;
- dma->device_cfg = dma_device_cfg_table[dev_no] ;
-
- /* Clear status register.*/
- dma->regs->DMA_ISR = 1<<ch;
-
- DPRINTK("%s old CCR=0x%.8x\n", __func__, dma->regs->DMA_CCR_CH[ch]) ;
-
- /* Apply new DMA config to DMA controller.*/
- dma->regs->DMA_CCR_CH[ch] = dma_device_cfg_table[dev_no].DefaultCCR ;
- DPRINTK("%s new CCR=0x%.8x\n", __func__, dma_device_cfg_table[dev_no].DefaultCCR) ;
- DPRINTK("%s old CCR=0x%.8x\n", __func__, dma->regs->DMA_CCR_CH[ch].CCR) ;
- if (device_cfg.DeviceReqType != MEMORY_DMA_REQ)
- dma->regs->DMA_CCR_CH[ch] |= device_cfg.DeviceReqType << DMA_REQ_ID_SHIFT;
- /*Device -> Memory(Read) && Memory(Write)i-->Device*/
- if (dev_no != MEMORY_DMA_REQ) {
- dma_mem_regs->mem_reg_group[ch].DMA_IF1DAR_CH = dma->device_cfg.MIF1addr;
- /*dma_mem_regs->mem_reg_group[ch].DMA_IF0CPR_CH = 0 ;*/
- }
- /*
- if (dev_no == MEMORY_DMA_REQ) {
- dma_mem_regs->mem_reg_group[ch].DMA_IF0CPR_CH = dma->des0_phy_addr;
- dma_mem_regs->mem_reg_group[ch].DMA_IF1CPR_CH = dma->des1_phy_addr;
- }
- */
- DPRINTK("%s new CCR=0x%.8x\n", __func__, dma->regs->DMA_CCR_CH[ch]) ;
-
- return 0;
-}
-
-/*=============================================================================*/
-/**/
-/* wmt_stop_dma - stop DMA in progress*/
-/* @regs: identifier for the channel to use*/
-/**/
-/* This stops DMA without clearing buffer pointers. Unlike*/
-/* clear_dma() this allows subsequent use of resume_dma()*/
-/* or get_dma_pos().*/
-/**/
-/* The @regs identifier is provided by a successful call to*/
-/* request_dma().*/
-/**/
-/*=============================================================================*/
-void wmt_stop_dma(dmach_t ch)
-{
- struct dma_info_s *dma;
-#ifdef DMA4_ERRATA
- unsigned int now_time = 0;
- unsigned int delay_time = 0;
-#endif
-
- if ((ch >= MAX_DMA_CHANNELS) ||
- (dma_chan[ch].in_use == 0)) {
- DPRINTK("%s: bad DMA identifier\n", __func__);
- return;
- }
-
- dma = &dma_chan[ch];
- dma->regs->DMA_CCR_CH[ch] &= ~(SYSTEM_DMA_REQ_EN);
- udelay(5);
-#ifdef DMA4_ERRATA
- if (dma->regs->DMA_CCR_CH[ch] & (SYSTEM_DMA_RUN)) {
- dma->regs->DMA_CCR_CH[ch] |= (DMA_UP_MEMREG_EN);/*update memory register before reading*/
- now_time = wmt_read_oscr();
- while (dma->regs->DMA_CCR_CH[ch] & (DMA_UP_MEMREG_EN)) {
- delay_time = wmt_read_oscr() - now_time;
- if (delay_time > 15) {/*5us*/
- DPRINTK("[%d]Warnning:up_mem_reg did not clear[%x]\n", ch, dma->regs->DMA_CCR_CH[ch]);
- dma->regs->DMA_CCR_CH[ch] &= ~DMA_UP_MEMREG_EN;/*clear DMA_UP_MEMREG_EN*/
- break;
- }
- }
- }
-#endif
- dma->regs->DMA_CCR_CH[ch] &= ~SYSTEM_DMA_RUN;
-}
-
-/*=============================================================================*/
-/**/
-/* wmt_resume_dma - resume DMA on a stopped channel*/
-/* @regs: identifier for the channel to use*/
-/**/
-/* This resumes DMA on a channel previously stopped with*/
-/* wmt_stop_dma().*/
-/**/
-/* The @regs identifier is provided by a successful call to*/
-/* wmt_request_dma().*/
-/**/
-/*=============================================================================*/
-void wmt_resume_dma(dmach_t ch)
-{
- struct dma_info_s *dma;
- struct dma_mem_reg_group_s dma_mem_reg ;
- dma = &dma_chan[ch] ;
- if (dma->regs->DMA_CCR_CH[ch] & DMA_ACTIVE) {/*if dma was active , disable dma first*/
- dma->regs->DMA_CCR_CH[ch] &= ~(SYSTEM_DMA_REQ_EN);
- udelay(5);
- dma->regs->DMA_CCR_CH[ch] &= ~(SYSTEM_DMA_RUN);
- }
- if ((ch >= MAX_DMA_CHANNELS) ||
- (dma_chan[ch].in_use == 0)) {
- DPRINTK("%s: bad DMA identifier\n", __func__);
- return;
- }
- dma_mem_reg = wmt_get_dma_pos_info(ch);
- revise_descript(ch, dma->device_cfg, dma_mem_reg);
- dma->regs->DMA_CCR_CH[ch] |= (SYSTEM_DMA_RUN | SYSTEM_DMA_REQ_EN);
-}
-
-/*=============================================================================*/
-/**/
-/* wmt_get_dma_pos_info - return current DMA position*/
-/* @ch: identifier for the channel to use*/
-/**/
-/* This function returns the current physical (or bus) address for the*/
-/* given DMA channel. If the channel is running i.e. not in a stopped*/
-/* state then the caller must disable interrupts prior calling this*/
-/* function and process the returned value before re-enabling them to*/
-/* prevent races with the completion interrupt handler and the callback*/
-/* function. The validation of the returned value is the caller's*/
-/* responsibility as well -- the hardware seems to return out of range*/
-/* values when the DMA engine completes a buffer.*/
-/**/
-/* The @ch identifier is provided by a successful call to*/
-/* wmt_request_dma().*/
-/**/
-/*=============================================================================*/
-struct dma_mem_reg_group_s wmt_get_dma_pos_info(dmach_t ch)
-{
- struct dma_mem_reg_group_s dma_mem_reg;
-#ifdef DMA4_ERRATA
- struct dma_info_s *dma;
- unsigned int now_time = 0;
- unsigned long flags;
- unsigned int delay_time = 0;
- dma = &dma_chan[ch];
-#endif
-
- if ((ch >= MAX_DMA_CHANNELS) ||
- (dma_chan[ch].in_use == 0)) {
- DPRINTK("%s: bad DMA identifier\n", __func__);
- goto out;
- }
-#ifdef DMA4_ERRATA
- if (dma->regs->DMA_CCR_CH[ch] & (SYSTEM_DMA_RUN)) {
- spin_lock_irqsave(&dma_list_lock, flags);
- dma->regs->DMA_CCR_CH[ch] |= (DMA_UP_MEMREG_EN);/*update memory register before reading*/
-
- now_time = wmt_read_oscr();
- while (dma->regs->DMA_CCR_CH[ch] & (DMA_UP_MEMREG_EN)) {
- delay_time = wmt_read_oscr() - now_time;
- if (delay_time > 15) {/*5us*/
- DPRINTK("[%d]Warnning:up_mem_reg did not clear[%x]\n", ch, dma->regs->DMA_CCR_CH[ch]);
- dma->regs->DMA_CCR_CH[ch] &= ~DMA_UP_MEMREG_EN;/*clear DMA_UP_MEMREG_EN*/
- break;
- }
-
- }
-
- spin_unlock_irqrestore(&dma_list_lock, flags);
- }
-#endif
-
- dma_mem_reg.DMA_IF0BAR_CH = dma_mem_regs->mem_reg_group[ch].DMA_IF0BAR_CH;
- dma_mem_reg.DMA_IF0CPR_CH = dma_mem_regs->mem_reg_group[ch].DMA_IF0CPR_CH;
- dma_mem_reg.DMA_IF0RBR_CH = dma_mem_regs->mem_reg_group[ch].DMA_IF0RBR_CH;
- dma_mem_reg.DMA_IF0DAR_CH = dma_mem_regs->mem_reg_group[ch].DMA_IF0DAR_CH;
- dma_mem_reg.DMA_IF1BAR_CH = dma_mem_regs->mem_reg_group[ch].DMA_IF1BAR_CH;
- dma_mem_reg.DMA_IF1CPR_CH = dma_mem_regs->mem_reg_group[ch].DMA_IF1CPR_CH;
- dma_mem_reg.DMA_IF1RBR_CH = dma_mem_regs->mem_reg_group[ch].DMA_IF1RBR_CH;
- dma_mem_reg.DMA_IF1DAR_CH = dma_mem_regs->mem_reg_group[ch].DMA_IF1DAR_CH;
-
-out:
- return dma_mem_reg;
-}
-
-/*=============================================================================*/
-/**/
-/* wmt_get_dma_pos - return current DMA position*/
-/* @ch: identifier for the channel to use*/
-/**/
-/* This function returns the current physical (or bus) address for the*/
-/* given DMA channel. If the channel is running i.e. not in a stopped*/
-/* state then the caller must disable interrupts prior calling this*/
-/* function and process the returned value before re-enabling them to*/
-/* prevent races with the completion interrupt handler and the callback*/
-/* function. The validation of the returned value is the caller's*/
-/* responsibility as well -- the hardware seems to return out of range*/
-/* values when the DMA engine completes a buffer.*/
-/**/
-/* The @ch identifier is provided by a successful call to*/
-/* wmt_request_dma().*/
-/**/
-/*=============================================================================*/
-unsigned int wmt_get_dma_pos(dmach_t ch)
-{
- struct dma_mem_reg_group_s dma_mem_reg;
- struct dma_info_s *dma;
-#ifdef DMA4_ERRATA
- unsigned long flags;
- unsigned int now_time;
- unsigned int delay_time;
-#endif
- dma = &dma_chan[ch];
-
- if ((ch >= MAX_DMA_CHANNELS) ||
- (dma_chan[ch].in_use == 0)) {
- DPRINTK("%s: bad DMA identifier\n", __func__);
- goto out;
- }
-#ifdef DAM4_ERRATA
- if (dma->regs->DMA_CCR_CH[ch] & (SYSTEM_DMA_RUN)) {
- spin_lock_irqsave(&dma_list_lock, flags);
- dma->regs->DMA_CCR_CH[ch] |= (DMA_UP_MEMREG_EN);/*update memory register before reading*/
- now_time = wmt_read_oscr();
- while (dma->regs->DMA_CCR_CH[ch] & (DMA_UP_MEMREG_EN)) {
- delay_time = wmt_read_oscr() - now_time;
- if (delay_time > 15) {/*5us*/
- dma->regs->DMA_CCR_CH[ch] &= ~DMA_UP_MEMREG_EN;/*clear DMA_UP_MEMREG_EN*/
- break;
- }
- }
- spin_unlock_irqrestore(&dma_list_lock, flags);
- }
-#endif
-
- dma_mem_reg.DMA_IF0BAR_CH = dma_mem_regs->mem_reg_group[ch].DMA_IF0BAR_CH;
- dma_mem_reg.DMA_IF0CPR_CH = dma_mem_regs->mem_reg_group[ch].DMA_IF0CPR_CH;
- dma_mem_reg.DMA_IF0RBR_CH = dma_mem_regs->mem_reg_group[ch].DMA_IF0RBR_CH;
- dma_mem_reg.DMA_IF0DAR_CH = dma_mem_regs->mem_reg_group[ch].DMA_IF0DAR_CH;
- dma_mem_reg.DMA_IF1BAR_CH = dma_mem_regs->mem_reg_group[ch].DMA_IF1BAR_CH;
- dma_mem_reg.DMA_IF1CPR_CH = dma_mem_regs->mem_reg_group[ch].DMA_IF1CPR_CH;
- dma_mem_reg.DMA_IF1RBR_CH = dma_mem_regs->mem_reg_group[ch].DMA_IF1RBR_CH;
- dma_mem_reg.DMA_IF1DAR_CH = dma_mem_regs->mem_reg_group[ch].DMA_IF1DAR_CH;
-
-out:
- return dma_mem_reg.DMA_IF0DAR_CH;
-}
-
-
-/*===========================================================================*/
-/* wmt_dma_busy*/
-/**/
-/* return: 1: busy , 0: not busy , other: fail*/
-/*===========================================================================*/
-int wmt_dma_busy(dmach_t ch)
-{
- struct dma_info_s *dma;
-
- dma = &dma_chan[ch];
- if (ch >= MAX_DMA_CHANNELS || (dma_chan[ch].in_use == 0)) {
- DPRINTK("%s: bad DMA identifier\n", __func__);
- return -1 ;
- }
-
- if (dma->regs->DMA_ISR & (1<<ch)) {
- dma->regs->DMA_ISR = (1<<ch); /*write 1 clear*/
- return 0 ;
- } else
- return 1;
-}
-
-/*===========================================================================*/
-/* wmt_dump_dma_regs*/
-/**/
-/* return: NULL*/
-/*===========================================================================*/
-void wmt_dump_dma_regs(dmach_t ch)
-{
- struct dma_info_s *dma = &dma_chan[ch] ;
- struct dma_regs_s *regs = dma->regs ;
-#ifdef DMA4_ERRATA
- unsigned long flags;
- unsigned int now_time = 0;
- unsigned int delay_time = 0;
-#endif
-
- printk("0x%8.8X : [0x%8.8X] GCR \n", \
- (unsigned int)&(regs->DMA_GCR) , (unsigned int)regs->DMA_GCR) ;
- printk("0x%8.8X : [0x%8.8X] MPRP \n", \
- (unsigned int)&(regs->DMA_MRPR) , (unsigned int)regs->DMA_MRPR) ;
- printk("0x%8.8X : [0x%8.8X] IER \n", \
- (unsigned int)&(regs->DMA_IER) , (unsigned int)regs->DMA_IER) ;
- printk("0x%8.8X : [0x%8.8X] ISR \n", \
- (unsigned int)&(regs->DMA_ISR) , (unsigned int)regs->DMA_ISR) ;
- printk("0x%8.8X : [0x%8.8X] TMR \n", \
- (unsigned int)&(regs->DMA_TMR) , (unsigned int)regs->DMA_TMR) ;
- printk("0x%8.8X : [0x%8.8X] CCR \n", \
- (unsigned int)&(regs->DMA_CCR_CH[ch]) , (unsigned int)regs->DMA_CCR_CH[ch]) ;
-
-#ifdef DMA4_ERRATA
- if (dma->regs->DMA_CCR_CH[ch] & (SYSTEM_DMA_RUN)) {
- spin_lock_irqsave(&dma_list_lock, flags);
- dma->regs->DMA_CCR_CH[ch] |= (DMA_UP_MEMREG_EN);/*update memory register before reading*/
-
- now_time = wmt_read_oscr();
- while (dma->regs->DMA_CCR_CH[ch] & (DMA_UP_MEMREG_EN)) {
- delay_time = wmt_read_oscr() - now_time;
- if (delay_time > 15) {/*5us*/
- DPRINTK("[%d]Warnning:up_mem_reg did not clear[%x]\n", ch, dma->regs->DMA_CCR_CH[ch]);
- dma->regs->DMA_CCR_CH[ch] &= ~DMA_UP_MEMREG_EN;/*clear DMA_UP_MEMREG_EN*/
- break;
- }
-
- }
-
- spin_unlock_irqrestore(&dma_list_lock, flags);
- }
-#endif
- printk("0x%8.8X : [0x%8.8X] Residue Bytes 0 \n", \
- (unsigned int)&(dma_mem_regs->mem_reg_group[ch].DMA_IF0RBR_CH)
- , (unsigned int)dma_mem_regs->mem_reg_group[ch].DMA_IF0RBR_CH) ;
- printk("0x%8.8X : [0x%8.8X] Data Address 0 \n", \
- (unsigned int)&(dma_mem_regs->mem_reg_group[ch].DMA_IF0DAR_CH)
- , (unsigned int)dma_mem_regs->mem_reg_group[ch].DMA_IF0DAR_CH) ;
- printk("0x%8.8X : [0x%8.8X] Branch Address 0 \n", \
- (unsigned int)&(dma_mem_regs->mem_reg_group[ch].DMA_IF0BAR_CH)
- , (unsigned int)dma_mem_regs->mem_reg_group[ch].DMA_IF0BAR_CH) ;
- printk("0x%8.8X : [0x%8.8X] Command Pointer 0 \n", \
- (unsigned int)&(dma_mem_regs->mem_reg_group[ch].DMA_IF0CPR_CH)
- , (unsigned int)dma_mem_regs->mem_reg_group[ch].DMA_IF0CPR_CH) ;
-
- printk("0x%8.8X : [0x%8.8X] Residue Bytes 1 \n", \
- (unsigned int)&(dma_mem_regs->mem_reg_group[ch].DMA_IF1RBR_CH)
- , (unsigned int)dma_mem_regs->mem_reg_group[ch].DMA_IF1RBR_CH) ;
- printk("0x%8.8X : [0x%8.8X] Data Address 1 \n", \
- (unsigned int)&(dma_mem_regs->mem_reg_group[ch].DMA_IF1DAR_CH)
- , (unsigned int)dma_mem_regs->mem_reg_group[ch].DMA_IF1DAR_CH) ;
- printk("0x%8.8X : [0x%8.8X] Branch Address 1 \n", \
- (unsigned int)&(dma_mem_regs->mem_reg_group[ch].DMA_IF1BAR_CH)
- , (unsigned int)dma_mem_regs->mem_reg_group[ch].DMA_IF1BAR_CH) ;
- printk("0x%8.8X : [0x%8.8X] Command Pointer 1 \n", \
- (unsigned int)&(dma_mem_regs->mem_reg_group[ch].DMA_IF1CPR_CH)
- , (unsigned int)dma_mem_regs->mem_reg_group[ch].DMA_IF1CPR_CH) ;
-
-}
-
-
-#ifdef CONFIG_PM
-static int dma_suspend(void)
-{
- return 0;
-}
-
-static void dma_resume(void)
-{
- struct dma_regs_s *dma_regs ;
- auto_pll_divisor(DEV_DMA, CLK_ENABLE, 0, 0);
- dma_regs = (struct dma_regs_s *) (io_p2v(DMA_CTRL_CFG_BASE_ADDR)) ;
- /*dma_regs->GCR = ( DMA_GCR_GDMA_ENABLE | DMA_GCR_PRIORITY_FIXED | DMA_GCR_GINT_ENABLE ) ;*/
- dma_regs->DMA_GCR |= DMA_GLOBAL_EN;
- dma_regs->DMA_ISR = ALL_INT_CLEAR;
- dma_regs->DMA_IER |= ALL_INT_EN;
- dma_regs->DMA_TMR &= ~SCHEDULE_RR_DISABLE; /*use RR schedule*/
- dma_regs->DMA_MRPR = (unsigned int)dma_mem_phy;
-}
-
-#else
-#define dma_suspend NULL
-#define dma_resume NULL
-#endif /* CONFIG_PM */
-
-
-static struct syscore_ops wmt_dma_syscore_ops = {
- .suspend = dma_suspend,
- .resume = dma_resume,
-};
-
-static int __init wmt_dma_init_devicefs(void)
-{
- register_syscore_ops(&wmt_dma_syscore_ops);
- return 0;
-}
-
-device_initcall(wmt_dma_init_devicefs);
-
-/*===========================================================================*/
-/* wmt_dma_init*/
-/**/
-/* return: 0*/
-/*===========================================================================*/
-static int __init
-wmt_dma_init(void)
-{
- int ch ;
- int ret = 0;
- struct dma_regs_s *dma_regs ;
- /*
- *(volatile unsigned int *)(0xD8130254) |= BIT5;
- */
- auto_pll_divisor(DEV_DMA, CLK_ENABLE, 0, 0);
-
- dma_regs = (struct dma_regs_s *) (io_p2v(DMA_CTRL_CFG_BASE_ADDR)) ;
-
- /**/
- /* software initial*/
- /**/
- dma_int.request_chans = 0 ;
- dma_int.regs = (struct dma_regs_s *) (io_p2v(DMA_CTRL_CFG_BASE_ADDR)) ;
-
- for (ch = 0 ; ch < MAX_DMA_CHANNELS ; ++ch) {
- dma_chan[ch].channel_no = ch ;
- dma_chan[ch].regs = (struct dma_regs_s *) (io_p2v(DMA_CTRL_CFG_BASE_ADDR)) ;
- dma_chan[ch].irq = ch ;
- dma_chan[ch].device_no = DEVICE_RESERVED ;
- dma_chan[ch].in_use = 0 ;
- }
-
- dma_mem_regs = (struct dma_mem_reg_s *) (io_p2v((DMA_CTRL_CFG_BASE_ADDR + DMA_MEM_REG_OFFSET)));
- if (!dma_mem_regs) {
- printk("dma memory register allocate failed\n");
- ret = -1;
- return ret;
- }
- dma_mem_phy = DMA_CTRL_CFG_BASE_ADDR + DMA_MEM_REG_OFFSET;
- DPRINTK("MEM_REGS ADDR:Virt = 0x%x , Phy = 0x%x\n", dma_mem_regs , dma_mem_phy);
-
- if (dma_mem_phy & 0x000000FF) {/*8 DW alignment*/
- printk("dma memory registers did not 8 DW alignment");
- ret = -1;
- return ret;
- }
-
- /**/
- /* hardware initial*/
- /**/
- dma_regs->DMA_GCR |= DMA_SW_RST ;
- dma_regs->DMA_GCR |= DMA_GLOBAL_EN;
- dma_regs->DMA_ISR = ALL_INT_CLEAR;
- dma_regs->DMA_IER |= ALL_INT_EN;
- dma_regs->DMA_TMR &= ~SCHEDULE_RR_DISABLE; /*use RR schedule*/
- dma_regs->DMA_MRPR = (unsigned int)dma_mem_phy;
- DPRINTK("0x%8.8X : [0x%8.8X] DMA_GSR_REG \n", \
- (unsigned int)&dma_regs->GSR , dma_regs->GSR) ;
-
- for (ch = 0 ; ch < MAX_DMA_CHANNELS ; ++ch) {
- dma_mem_regs->mem_reg_group[ch].DMA_IF0CPR_CH = 0x100;
- dma_mem_regs->mem_reg_group[ch].DMA_IF1DAR_CH = 0x100;
- dma_regs->DMA_CCR_CH[ch] = 0x0;
- }
- DPRINTK("0x%8.8X : [0x%8.8X] DMA_GCR_REG \n", \
- (unsigned int)&dma_regs->DMA_GCR , dma_regs->DMA_GCR) ;
- /*
- for (ch = 0; ch < MAX_DMA_CHANNELS ; ++ch)
- request_irq(dma_irq_no[ch], dma_irq_handler, IRQF_DISABLED, "dma", NULL);
- */
- request_irq(IRQ_DMA_NONS, dma_irq_handler, IRQF_DISABLED, "dma", NULL);
-
- return ret;
-}
-
-/*===========================================================================*/
-/* dma_exit*/
-/**/
-/* return: 0*/
-/*===========================================================================*/
-static void __exit
-wmt_dma_exit(void)
-{
- int ch;
- /*remove_proc_entry("driver/dma", NULL);*/
- dma_free_coherent(NULL,
- sizeof(struct dma_mem_reg_s),
- dma_mem_regs,
- dma_mem_phy);
-
- for (ch = 0; ch < MAX_DMA_CHANNELS ; ++ch)
- free_irq(dma_irq_no[ch], NULL);
-}
-
-__initcall(wmt_dma_init);
-__exitcall(wmt_dma_exit);
-
-EXPORT_SYMBOL(wmt_request_dma);
-EXPORT_SYMBOL(wmt_setup_dma);
-EXPORT_SYMBOL(wmt_free_dma);
-EXPORT_SYMBOL(wmt_clear_dma);
-EXPORT_SYMBOL(wmt_reset_dma);
-EXPORT_SYMBOL(wmt_start_dma);
-EXPORT_SYMBOL(wmt_stop_dma);
-EXPORT_SYMBOL(wmt_resume_dma);
-EXPORT_SYMBOL(wmt_get_dma_pos_info);
-EXPORT_SYMBOL(wmt_dma_busy);
-EXPORT_SYMBOL(wmt_dump_dma_regs);