static struct rk2818_dma rk2818_dma[MAX_DMA_CHANNELS];
+static struct tasklet_struct rk2818_dma_tasklet;
+
const static char *rk28_dma_dev_id[] = {
"sd_mmc",
"uart_2",
spin_lock(&rk28dma->lock);
DISABLE_DWDMA(dma_ch);
-
+ while (GET_DWDMA_STATUS(dma_ch))
+ cpu_relax();
+
spin_unlock(&rk28dma->lock);
return 0;
rk28dma->dma_llp_phy = NULL;
}
- rk2818_dma[dma_ch].dev_info = &rk28_dev_info[i];
+ rk28dma->dev_info = &rk28_dev_info[i];
/* clear interrupt */
CLR_DWDMA_INTR(dma_ch);
- /* Unmask interrupt */
- UN_MASK_DWDMA_INTR(dma_ch);
-
spin_unlock(&rk28dma->lock);
//printk(KERN_INFO "exit dwdma request device %d\n", i);
/* clear interrupt */
CLR_DWDMA_INTR(dma_ch);
- /* Mask interrupt */
- MASK_DWDMA_INTR(dma_ch);
-
if (dma_ch < RK28_DMA_CH2) {
if (!rk28dma->dma_llp_vir) {
printk(KERN_ERR "dma_free: no dma space can be free by virtual channel %d\n", dma_ch);
}
/**
- * rk28_dma_irq_handler - irq callback function
+ * rk28_dma_tasklet - irq callback function
*
*/
-static irqreturn_t rk28_dma_irq_handler(int irq, void *dev_id)
+static void rk28_dma_tasklet(unsigned long data)
{
int i, raw_status;
struct rk2818_dma *rk28dma;
-
+
raw_status = read_dma_reg(DWDMA_RawTfr);
for (i = 0; i < MAX_DMA_CHANNELS; i++) {
rk28dma->dma_t.active = 0;
if (rk28dma->dma_t.irqHandle) {
- rk28dma->dma_t.irqHandle(i, rk28dma->dma_t.data);
+ void *data = rk28dma->dma_t.data;
+ rk28dma->dma_t.irqHandle(i, data);
} else {
- //printk(KERN_WARNING "dma_irq: no IRQ handler for DMA channel %d\n", i);
+ printk(KERN_WARNING "dma_irq: no IRQ handler for DMA channel %d\n", i);
}
}
}
+ /*
+ * Re-enable interrupts
+ */
+ UN_MASK_DWDMA_ALL_TRF_INTR;
+}
+
+/**
+ * rk28_dma_irq_handler - irq callback function
+ *
+ */
+static irqreturn_t rk28_dma_irq_handler(int irq, void *dev_id)
+{
+ /*
+ * Just disable the interrupts. We'll turn them back on in the
+ * softirq handler.
+ */
+ MASK_DWDMA_ALL_TRF_INTR;
+
+ tasklet_schedule(&rk2818_dma_tasklet);
+
return IRQ_HANDLED;
}
printk(KERN_INFO "enter dwdma init\n");
- ret = request_irq(RK28_DMA_IRQ_NUM, rk28_dma_irq_handler, 0, "DMA", NULL);
- if (ret < 0) {
- printk(KERN_CRIT "Can't register IRQ for DMA\n");
- return ret;
- }
-
for (i = 0; i < MAX_DMA_CHANNELS; i++) {
rk2818_dma[i].dma_t.irqHandle = NULL;
rk2818_dma[i].dma_t.data = NULL;
rk2818_dma[i].length = 0;
}
- /* enable DMA module */
- write_dma_reg(DWDMA_DmaCfgReg, 0x01);
-
/* clear all interrupts */
write_dma_reg(DWDMA_ClearBlock, 0x3f3f);
write_dma_reg(DWDMA_ClearTfr, 0x3f3f);
write_dma_reg(DWDMA_ClearDstTran, 0x3f3f);
write_dma_reg(DWDMA_ClearErr, 0x3f3f);
+ /*mask all interrupts*/
+ write_dma_reg(DWDMA_MaskBlock, 0x3f00);
+ write_dma_reg(DWDMA_MaskSrcTran, 0x3f00);
+ write_dma_reg(DWDMA_MaskDstTran, 0x3f00);
+ write_dma_reg(DWDMA_MaskErr, 0x3f00);
+
+ /*unmask transfer completion interrupt*/
+ UN_MASK_DWDMA_ALL_TRF_INTR;
+
+ ret = request_irq(RK28_DMA_IRQ_NUM, rk28_dma_irq_handler, 0, "DMA", NULL);
+ if (ret < 0) {
+ printk(KERN_CRIT "Can't register IRQ for DMA\n");
+ return ret;
+ }
+
+ tasklet_init(&rk2818_dma_tasklet, rk28_dma_tasklet, NULL);
+
+ /* enable DMA module */
+ write_dma_reg(DWDMA_DmaCfgReg, 0x01);
+
printk(KERN_INFO "exit dwdma init\n");
return 0;
#define CLR_DWDMA_INTR(dma_ch) write_dma_reg(DWDMA_ClearTfr, 0x101<<dma_ch)
/* Unmask interrupt */
-#define UN_MASK_DWDMA_INTR(dma_ch) mask_dma_reg(DWDMA_MaskTfr, 0x101<<dma_ch, 0x101<<dma_ch)
+#define UN_MASK_DWDMA_ALL_TRF_INTR write_dma_reg(DWDMA_MaskTfr, 0x3f3f)//mask_dma_reg(DWDMA_MaskTfr, 0x101<<dma_ch, 0x101<<dma_ch)
/* Mask interrupt */
-#define MASK_DWDMA_INTR(dma_ch) mask_dma_reg(DWDMA_MaskTfr, 0x101<<dma_ch, 0x100<<dma_ch)
+#define MASK_DWDMA_ALL_TRF_INTR write_dma_reg(DWDMA_MaskTfr, 0x3f00)//mask_dma_reg(DWDMA_MaskTfr, 0x101<<dma_ch, 0x100<<dma_ch)
/* Enable channel */
#define ENABLE_DWDMA(dma_ch) mask_dma_reg(DWDMA_ChEnReg, 0x101<<dma_ch, 0x101<<dma_ch)
/* Disable channel */
#define DISABLE_DWDMA(dma_ch) mask_dma_reg(DWDMA_ChEnReg, 0x101<<dma_ch, 0x100<<dma_ch)
+ /* Disable channel */
+#define GET_DWDMA_STATUS(dma_ch) read_dma_reg(DWDMA_ChEnReg) & (0x001<<dma_ch)
+
/**************************/
#define RK28_DMA_IRQ_NUM 0
-#define RK28_MAX_DMA_LLPS 100 /*max dma sg count*/
+#define RK28_MAX_DMA_LLPS 64 /*max dma sg count*/
#define RK28_DMA_CH0A1_MAX_LEN 4095U
#define RK28_DMA_CH2_MAX_LEN 2047U
llp_t *llp;
unsigned int ctll;
unsigned int size;
+ unsigned int sstat;
+ unsigned int dstat;
};
struct rk28_dma_dev {
spinlock_t lock;
};
-//#define test_dma
+#define test_dma
/*devicd id list*/
#define RK28_DMA_SD_MMC 0