[PATCH 12/13] mdma:dmaengine:update mdma for tdma

zhaoy zhaoy at marvell.com
Tue Feb 28 02:27:44 EST 2012


	1, do some update to add mdma to the
	dma engine as adma

Change-Id: I514b247e0c2301fc48b1f1980562f3c50d6a6455
Signed-off-by: zhaoy <zhaoy at marvell.com>
---
 drivers/char/mmp2_mdma.c |  273 ++++++++++++++--------------------------------
 1 files changed, 84 insertions(+), 189 deletions(-)

diff --git a/drivers/char/mmp2_mdma.c b/drivers/char/mmp2_mdma.c
index c16b94a..72fee88 100644
--- a/drivers/char/mmp2_mdma.c
+++ b/drivers/char/mmp2_mdma.c
@@ -37,8 +37,8 @@ static void *dma_desc_array_ch1 = NULL;
 static void *dma_desc_array_ch2 = NULL;
 static dma_addr_t dma_desc_array_phys_ch1;
 static dma_addr_t dma_desc_array_phys_ch2;
-static struct completion complete_ch1;
-static struct completion complete_ch2;
+static struct completion complete_memcpy;
+static struct completion complete_memset;
 
 static unsigned long uva_to_pa(struct mm_struct *mm, unsigned long addr)
 {
@@ -68,43 +68,41 @@ static unsigned long uva_to_pa(struct mm_struct *mm, unsigned long addr)
 	return ret;
 }
 
-static void mdma_irq(int channel, void *data)
+static void mdma_irq(void *data)
 {
-	unsigned int base_register = mmp_get_dma_reg_base(channel);
-
-	if(base_register){
-		if (TDISR(base_register) & 0x1) {
-			if(channel == MDMA1_CH0)
-				complete(&complete_ch1);
-			else
-				complete(&complete_ch2);
-			if(TDISR(base_register) & 0xc)
-				printk(KERN_ERR "MDMA error 0x%x on channel %d \n",
-					TDISR(base_register), channel);
-		} else {
-			printk(KERN_ERR "MDMA error on channel %d \n", channel);
-		}
-		TDISR(base_register) = 0;
-	}
+	struct completion *mdma_complete = data;
+
+	complete(mdma_complete);
 
 	return;
 }
 
+static bool filter(struct dma_chan *chan, void *param)
+{
+	struct mmp_tdma_data *tdma_data = param;
+
+	if (!mmp_mdma_is_this_type(chan))
+		return false;
+
+	chan->private = tdma_data;
+
+	return true;
+}
 /*
  * len requires at least 8bytes alignment. 128bytes alignment will get better performance.
  * Alignment: 8, 16, 32, 64, 128. The bigger, the better.
  * source and destination address aslo need alignment with burst size.
  */
+struct mmp_tdma_data tdma_data_pmemcpy;
 unsigned long mdma_pmemcpy(unsigned long pdst, unsigned long psrc, unsigned int len)
 {
-	int ret, dma_ch;
-	unsigned int base_register;
-	unsigned int dcmd, mdma_dcr;
+	int ret;
 	unsigned long len_tmp, len_total;
-	struct pxa910_squ_desc *dma_desc_tmp;
-	dma_addr_t dma_desc_p_tmp;
 	unsigned long srcphyaddr = psrc;
 	unsigned long dstphyaddr = pdst;
+	struct dma_chan *dma_chan;
+	dma_cap_mask_t mask;
+	struct dma_async_tx_descriptor *desc;
 
 	if (srcphyaddr == 0 || dstphyaddr == 0)
 		return -1;
@@ -124,95 +122,44 @@ unsigned long mdma_pmemcpy(unsigned long pdst, unsigned long psrc, unsigned int
 		return -1;
 	}
 
-	ret = mmp_request_dma("mdma_memcpy", MDMA1_CH0,
-					mdma_irq, NULL);
-	if (ret < 0){
-		ret = mmp_request_dma("mdma_memcpy", MDMA1_CH1,
-						mdma_irq, NULL);
-		if (ret < 0){
-			printk(KERN_ERR	"Can't request MDMA for memcpy\n");
-			return -ENODEV;
-		}else{
-			dma_ch = MDMA1_CH1;
-		}
-	}else{
-		dma_ch = MDMA1_CH0;
-	}
-
-	if(dma_ch == MDMA1_CH0){
-		dma_desc_tmp = dma_desc_array_ch1;
-		dma_desc_p_tmp = dma_desc_array_phys_ch1;
-	}else{
-		dma_desc_tmp = dma_desc_array_ch2;
-		dma_desc_p_tmp = dma_desc_array_phys_ch2;
-	}
-
-	len_total = len;
-	while(len_total) {
-		len_tmp = len_total>SINGLE_DESC_TRANS_MAX ?
-				SINGLE_DESC_TRANS_MAX : len_total;
-		dma_desc_tmp->nxt_desc = dma_desc_p_tmp + sizeof(struct pxa910_squ_desc);
-		dma_desc_tmp->src_addr = srcphyaddr;
-		dma_desc_tmp->dst_addr = dstphyaddr;
-		dma_desc_tmp->byte_cnt = len_tmp;
-		if (len_total <= SINGLE_DESC_TRANS_MAX) {
-			dma_desc_tmp->nxt_desc = 0;
-			break;
-		}
-		len_total -= len_tmp;
-		dma_desc_tmp ++;
-		dma_desc_p_tmp += sizeof(struct pxa910_squ_desc);
-		srcphyaddr += len_tmp;
-		dstphyaddr += len_tmp;
-	}
-
 	if (!((len & 0x7f) || (srcphyaddr & 0x7f) || (dstphyaddr & 0x7f)))
-		dcmd = MDCR_DST_ADDR_INC | MDCR_SRC_ADDR_INC | MDCR_TRANSMOD |
-			MDCR_DMA_BURST_128B | SDCR_FETCHND;
+		tdma_data_pmemcpy.bus_size = MDCR_DMA_BURST_128B;
 	else if (!((len & 0x3f) || (srcphyaddr & 0x3f) || (dstphyaddr & 0x3f)))
-		dcmd = MDCR_DST_ADDR_INC | MDCR_SRC_ADDR_INC | MDCR_TRANSMOD |
-			MDCR_DMA_BURST_64B | SDCR_FETCHND;
+		tdma_data_pmemcpy.bus_size = MDCR_DMA_BURST_64B;
 	else if (!((len & 0x1f) || (srcphyaddr & 0x1f) || (dstphyaddr & 0x1f)))
-		dcmd = MDCR_DST_ADDR_INC | MDCR_SRC_ADDR_INC | MDCR_TRANSMOD |
-			MDCR_DMA_BURST_32B | SDCR_FETCHND;
+		tdma_data_pmemcpy.bus_size = MDCR_DMA_BURST_32B;
 	else if (!((len & 0xf) || (srcphyaddr & 0xf) || (dstphyaddr & 0xf)))
-		dcmd = MDCR_DST_ADDR_INC | MDCR_SRC_ADDR_INC | MDCR_TRANSMOD |
-			MDCR_DMA_BURST_16B | SDCR_FETCHND;
-	else
-		dcmd = MDCR_DST_ADDR_INC | MDCR_SRC_ADDR_INC | MDCR_TRANSMOD |
-			MDCR_DMA_BURST_8B | SDCR_FETCHND;
-
-	base_register = mmp_get_dma_reg_base(dma_ch);
-	TDCR(base_register)= (dcmd) & (~MDCR_CHANEN);
-	TDIMR(base_register) = MDIMR_COMP;
-	if(dma_ch == MDMA1_CH0)
-		TDNDPR(base_register) = dma_desc_array_phys_ch1;
+		tdma_data_pmemcpy.bus_size = MDCR_DMA_BURST_16B;
 	else
-		TDNDPR(base_register) = dma_desc_array_phys_ch2;
-	if(dma_ch == MDMA1_CH0){
-		init_completion(&complete_ch1);
-	}else{
-		init_completion(&complete_ch2);
-	}
+		tdma_data_pmemcpy.bus_size = MDCR_DMA_BURST_8B;
 
+	/* Try to grab a DMA channel */
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_MEMCPY, mask);
+	dma_chan = dma_request_channel(mask, filter, &tdma_data_pmemcpy);
 
-	TDCR(base_register)= dcmd | MDCR_CHANEN;
+	len_total = len;
+	len_tmp = len_total > SINGLE_DESC_TRANS_MAX ?
+				SINGLE_DESC_TRANS_MAX : len_total;
 
-	if(dma_ch == MDMA1_CH0){
-		ret = wait_for_completion_timeout(&complete_ch1, 10*HZ);
-	}else{
-		ret = wait_for_completion_timeout(&complete_ch2, 10*HZ);
-	}
+	desc = dma_chan->device->device_prep_dma_memcpy(
+			dma_chan, dstphyaddr, srcphyaddr, len_total,
+			DMA_BIDIRECTIONAL);
 
-	TDIMR(base_register) = 0;
-	mdma_dcr = TDCR(base_register);
-	if (mdma_dcr & TDCR_CHANACT) {
-		TDCR(base_register) = mdma_dcr | TDCR_ABR;
-	}
-	while (mdma_dcr & TDCR_CHANACT) {
-		mdma_dcr = TDCR(base_register);
-	}
-	mmp_free_dma(dma_ch);
+	/* this completion will be finished after mdma irq */
+	init_completion(&complete_memcpy);
+
+	desc->callback = mdma_irq;
+	desc->callback_param = &complete_memcpy;
+
+	/* start dma transfer */
+	dmaengine_submit(desc);
+
+	ret = wait_for_completion_timeout(&complete_memcpy, 10*HZ);
+
+	/* release dma channel */
+	dma_release_channel(dma_chan);
+	dma_chan = NULL;
 
 	if (ret)
 		return len;
@@ -227,15 +174,15 @@ EXPORT_SYMBOL(mdma_pmemcpy);
  * destination address aslo need alignment with burst size.
  * data requires 32bits.
  */
+struct mmp_tdma_data tdma_data_pmemset;
 unsigned long mdma_pmemset(unsigned long paddr, unsigned long c, unsigned int len)
 {
-	int ret, dma_ch;
-	unsigned int base_register;
-	unsigned int dcmd, mdma_dcr;
+	int ret;
 	unsigned long len_tmp, len_total;
-	struct pxa910_squ_desc *dma_desc_tmp;
-	dma_addr_t dma_desc_p_tmp;
 	unsigned long dstphyaddr = paddr;
+	struct dma_chan *dma_chan;
+	dma_cap_mask_t mask;
+	struct dma_async_tx_descriptor *desc;
 
 	if (dstphyaddr == 0)
 		return -1;
@@ -250,95 +197,43 @@ unsigned long mdma_pmemset(unsigned long paddr, unsigned long c, unsigned int le
 		return -1;
 	}
 
-	ret = mmp_request_dma("mdma_memcpy", MDMA1_CH0,
-					mdma_irq, NULL);
-	if (ret < 0){
-		ret = mmp_request_dma("mdma_memcpy", MDMA1_CH1,
-						mdma_irq, NULL);
-		if (ret < 0){
-			printk(KERN_ERR	"Can't request MDMA for memcpy\n");
-			return -ENODEV;
-		}else{
-			dma_ch = MDMA1_CH1;
-		}
-	}else{
-		dma_ch = MDMA1_CH0;
-	}
-
-	if(dma_ch == MDMA1_CH0){
-		dma_desc_tmp = dma_desc_array_ch1;
-		dma_desc_p_tmp = dma_desc_array_phys_ch1;
-	}else{
-		dma_desc_tmp = dma_desc_array_ch2;
-		dma_desc_p_tmp = dma_desc_array_phys_ch2;
-	}
-
-	len_total = len;
-	while(len_total) {
-		len_tmp = len_total>SINGLE_DESC_TRANS_MAX ?
-				SINGLE_DESC_TRANS_MAX : len_total;
-		dma_desc_tmp->nxt_desc = dma_desc_p_tmp + sizeof(struct pxa910_squ_desc);
-		dma_desc_tmp->src_addr = 0;
-		dma_desc_tmp->dst_addr = dstphyaddr;
-		dma_desc_tmp->byte_cnt = len_tmp;
-		if (len_total <= SINGLE_DESC_TRANS_MAX) {
-			dma_desc_tmp->nxt_desc = 0;
-			break;
-		}
-		len_total -= len_tmp;
-		dma_desc_tmp ++;
-		dma_desc_p_tmp += sizeof(struct pxa910_squ_desc);
-		dstphyaddr += len_tmp;
-	}
-
 	if (!((len & 0x7f) || (dstphyaddr & 0x7f)))
-		dcmd = MDCR_DST_ADDR_INC | MDCR_SRC_ADDR_HOLD | MDCR_TRANSMOD |
-			MDCR_FILLMOD | MDCR_DMA_BURST_128B | SDCR_FETCHND;
+		tdma_data_pmemset.bus_size = MDCR_FILLMOD | MDCR_DMA_BURST_128B;
 	else if (!((len & 0x3f) || (dstphyaddr & 0x3f)))
-		dcmd = MDCR_DST_ADDR_INC | MDCR_SRC_ADDR_HOLD | MDCR_TRANSMOD |
-			MDCR_FILLMOD | MDCR_DMA_BURST_64B | SDCR_FETCHND;
+		tdma_data_pmemset.bus_size = MDCR_FILLMOD | MDCR_DMA_BURST_64B;
 	else if (!((len & 0x1f) || (dstphyaddr & 0x1f)))
-		dcmd = MDCR_DST_ADDR_INC | MDCR_SRC_ADDR_HOLD | MDCR_TRANSMOD |
-			MDCR_FILLMOD | MDCR_DMA_BURST_32B | SDCR_FETCHND;
+		tdma_data_pmemset.bus_size = MDCR_FILLMOD | MDCR_DMA_BURST_32B;
 	else if (!((len & 0xf) || (dstphyaddr & 0xf)))
-		dcmd = MDCR_DST_ADDR_INC | MDCR_SRC_ADDR_HOLD | MDCR_TRANSMOD |
-			MDCR_FILLMOD | MDCR_DMA_BURST_16B | SDCR_FETCHND;
-	else
-		dcmd = MDCR_DST_ADDR_INC | MDCR_SRC_ADDR_HOLD | MDCR_TRANSMOD |
-			MDCR_FILLMOD | MDCR_DMA_BURST_8B | SDCR_FETCHND;
-
-	base_register = mmp_get_dma_reg_base(dma_ch);
-	TDCR(base_register)= (dcmd) & (~MDCR_CHANEN);
-	TDIMR(base_register) = MDIMR_COMP;
-	if(dma_ch == MDMA1_CH0)
-		TDNDPR(base_register) = dma_desc_array_phys_ch1;
+		tdma_data_pmemset.bus_size = MDCR_FILLMOD | MDCR_DMA_BURST_16B;
 	else
-		TDNDPR(base_register) = dma_desc_array_phys_ch2;
-	MMP2_FILL_DATA(base_register) = c;
+		tdma_data_pmemset.bus_size = MDCR_FILLMOD | MDCR_DMA_BURST_8B;
 
-	if(dma_ch == MDMA1_CH0){
-		init_completion(&complete_ch1);
-	}else{
-		init_completion(&complete_ch2);
-	}
+	/* Try to grab a DMA channel */
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_MEMSET, mask);
+	dma_chan = dma_request_channel(mask, filter, &tdma_data_pmemset);
 
-	TDCR(base_register)= dcmd | MDCR_CHANEN;
+	len_total = len;
+	len_tmp = len_total > SINGLE_DESC_TRANS_MAX ?
+				SINGLE_DESC_TRANS_MAX : len_total;
+	desc = dma_chan->device->device_prep_dma_memset(
+			dma_chan, dstphyaddr, c, len_total,
+			DMA_BIDIRECTIONAL);
 
-	if(dma_ch == MDMA1_CH0){
-		ret = wait_for_completion_timeout(&complete_ch1, 10*HZ);
-	}else{
-		ret = wait_for_completion_timeout(&complete_ch2, 10*HZ);
-	}
+	/* this completion will be finished after mdma irq */
+	init_completion(&complete_memset);
 
-	TDIMR(base_register) = 0;
-	mdma_dcr = TDCR(base_register);
-	if (mdma_dcr & TDCR_CHANACT) {
-		TDCR(base_register) = mdma_dcr | TDCR_ABR;
-	}
-	while (mdma_dcr & TDCR_CHANACT) {
-		mdma_dcr = TDCR(base_register);
-	}
-	mmp_free_dma(dma_ch);
+	desc->callback = mdma_irq;
+	desc->callback_param = &complete_memset;
+
+	/* start dma transfer */
+	dmaengine_submit(desc);
+
+	ret = wait_for_completion_timeout(&complete_memset, 10*HZ);
+
+	/* release dma channel */
+	dma_release_channel(dma_chan);
+	dma_chan = NULL;
 
 	if (ret)
 		return len;
-- 
1.7.0.4




More information about the linux-arm-kernel mailing list