linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* Question about ppc4xx_dma.h
@ 2002-08-20 15:26 jim
  2002-08-20 23:18 ` akuster
  0 siblings, 1 reply; 6+ messages in thread
From: jim @ 2002-08-20 15:26 UTC (permalink / raw)
  To: linuxppc-embedded


I've been trying to get DMA working on the 405GP and I've run across
something in ppc4xx_dma.h.

In the function 'enable_dma' the following piece of code appears:

(begin excerpt)
	/* for other xfer modes, the addresses are already set */
	control = mfdcr(DCRN_DMACR0);
	control &= ~(DMA_TM_MASK | DMA_TD);	/* clear all mode bits */
	if (p_dma_ch->mode == DMA_MODE_MM) {
		/* software initiated memory to memory */
		control |= control | DMA_ETD_OUTPUT | DMA_TCE_ENABLE;
	}
	control |= (p_dma_ch->mode | DMA_CH_ENABLE);
	mtdcr(DCRN_DMACR0, control);
(end excerpt)

It looks to me like this code will always read/write the control register for
DMA channel 0 regardless of the channel specified by the parameter 'dmanr'
that is passed to the function.  Is this observation correct?  What would the
fix be, if so?

Also, does anyone have a short piece of code that shows how to start a DMA
read on the 405?

Thanks,
Jim

** Sent via the linuxppc-embedded mail list. See http://lists.linuxppc.org/

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Question about ppc4xx_dma.h
  2002-08-20 15:26 Question about ppc4xx_dma.h jim
@ 2002-08-20 23:18 ` akuster
  2002-08-21 19:39   ` akuster
  0 siblings, 1 reply; 6+ messages in thread
From: akuster @ 2002-08-20 23:18 UTC (permalink / raw)
  To: jim; +Cc: linuxppc-embedded


jim wrote:
> I've been trying to get DMA working on the 405GP and I've run across
> something in ppc4xx_dma.h.
>
> In the function 'enable_dma' the following piece of code appears:
>
> (begin excerpt)
> 	/* for other xfer modes, the addresses are already set */
> 	control = mfdcr(DCRN_DMACR0);
> 	control &= ~(DMA_TM_MASK | DMA_TD);	/* clear all mode bits */
> 	if (p_dma_ch->mode == DMA_MODE_MM) {
> 		/* software initiated memory to memory */
> 		control |= control | DMA_ETD_OUTPUT | DMA_TCE_ENABLE;
> 	}
> 	control |= (p_dma_ch->mode | DMA_CH_ENABLE);
> 	mtdcr(DCRN_DMACR0, control);
> (end excerpt)
>
> It looks to me like this code will always read/write the control register for
> DMA channel 0 regardless of the channel specified by the parameter 'dmanr'
> that is passed to the function.  Is this observation correct?

good catch.

>What would the
> fix be, if so?
>
Most likey switch statment like the disable has.

give me a day

Armin


** Sent via the linuxppc-embedded mail list. See http://lists.linuxppc.org/

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Question about ppc4xx_dma.h
  2002-08-20 23:18 ` akuster
@ 2002-08-21 19:39   ` akuster
  2002-08-21 22:17     ` Todd Poynor
  0 siblings, 1 reply; 6+ messages in thread
From: akuster @ 2002-08-21 19:39 UTC (permalink / raw)
  To: akuster; +Cc: jim, linuxppc-embedded

[-- Attachment #1: Type: text/plain, Size: 1119 bytes --]

akuster wrote:
>
> jim wrote:
>
>> I've been trying to get DMA working on the 405GP and I've run across
>> something in ppc4xx_dma.h.
>>
>> In the function 'enable_dma' the following piece of code appears:
>>
>> (begin excerpt)
>>     /* for other xfer modes, the addresses are already set */
>>     control = mfdcr(DCRN_DMACR0);
>>     control &= ~(DMA_TM_MASK | DMA_TD);    /* clear all mode bits */
>>     if (p_dma_ch->mode == DMA_MODE_MM) {
>>         /* software initiated memory to memory */
>>         control |= control | DMA_ETD_OUTPUT | DMA_TCE_ENABLE;
>>     }
>>     control |= (p_dma_ch->mode | DMA_CH_ENABLE);
>>     mtdcr(DCRN_DMACR0, control);
>> (end excerpt)
>>
>> It looks to me like this code will always read/write the control
>> register for
>> DMA channel 0 regardless of the channel specified by the parameter
>> 'dmanr'
>> that is passed to the function.  Is this observation correct?
>
>
> good catch.
>
>> What would the
>> fix be, if so?
>>
> Most likey switch statment like the disable has.
>
> give me a day
>
> Armin
>
>
>
>
>

Here is the patch , please let me know it it helps.

Armin

[-- Attachment #2: dma_0821.patch.gz --]
[-- Type: application/x-gunzip, Size: 1013 bytes --]

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Question about ppc4xx_dma.h
  2002-08-21 19:39   ` akuster
@ 2002-08-21 22:17     ` Todd Poynor
  2002-08-22  6:18       ` akuster
  2002-08-27  3:44       ` akuster
  0 siblings, 2 replies; 6+ messages in thread
From: Todd Poynor @ 2002-08-21 22:17 UTC (permalink / raw)
  To: akuster; +Cc: jim, linuxppc-embedded


Noticed that the order of clearing the old transfer mode bits and
setting the p_dma_ch->mode bits is reversed in the new patch, not sure
if this causes problems:

+       tmp_cntl |= (p_dma_ch->mode | DMA_CH_ENABLE);
+
+       switch (dmanr) {
+       case 0:
+               control = mfdcr(DCRN_DMACR0);
+               control |= tmp_cntl;
+               control &= ~(DMA_TM_MASK | DMA_TD);     /* clear all
mode bits */

This seems to set and then clear the p_dma_ch->mode bits in control
prior to writing to the DMACR, a problem?


--
Todd


** Sent via the linuxppc-embedded mail list. See http://lists.linuxppc.org/

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Question about ppc4xx_dma.h
  2002-08-21 22:17     ` Todd Poynor
@ 2002-08-22  6:18       ` akuster
  2002-08-27  3:44       ` akuster
  1 sibling, 0 replies; 6+ messages in thread
From: akuster @ 2002-08-22  6:18 UTC (permalink / raw)
  To: Todd Poynor; +Cc: jim, linuxppc-embedded


Todd Poynor wrote:
>
> Noticed that the order of clearing the old transfer mode bits and
> setting the p_dma_ch->mode bits is reversed in the new patch, not sure
> if this causes problems:
>
> +       tmp_cntl |= (p_dma_ch->mode | DMA_CH_ENABLE);
> +
> +       switch (dmanr) {
> +       case 0:
> +               control = mfdcr(DCRN_DMACR0);
> +               control |= tmp_cntl;
> +               control &= ~(DMA_TM_MASK | DMA_TD);     /* clear all
> mode bits */
>
> This seems to set and then clear the p_dma_ch->mode bits in control
> prior to writing to the DMACR, a problem?
>
>
> --
> Todd
>

Todd,

yeap, looks like it.

armin


** Sent via the linuxppc-embedded mail list. See http://lists.linuxppc.org/

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Question about ppc4xx_dma.h
  2002-08-21 22:17     ` Todd Poynor
  2002-08-22  6:18       ` akuster
@ 2002-08-27  3:44       ` akuster
  1 sibling, 0 replies; 6+ messages in thread
From: akuster @ 2002-08-27  3:44 UTC (permalink / raw)
  To: Todd Poynor; +Cc: jim, linuxppc-embedded

[-- Attachment #1: Type: text/plain, Size: 898 bytes --]

Todd Poynor wrote:
>
> Noticed that the order of clearing the old transfer mode bits and
> setting the p_dma_ch->mode bits is reversed in the new patch, not sure
> if this causes problems:
>
> +       tmp_cntl |= (p_dma_ch->mode | DMA_CH_ENABLE);
> +
> +       switch (dmanr) {
> +       case 0:
> +               control = mfdcr(DCRN_DMACR0);
> +               control |= tmp_cntl;
> +               control &= ~(DMA_TM_MASK | DMA_TD);     /* clear all
> mode bits */
>
> This seems to set and then clear the p_dma_ch->mode bits in control
> prior to writing to the DMACR, a problem?
>
>
> --
> Todd
>
>
>
>
>

Here is a patch that should address the above issue.  I put in
additional checks for if a the current dma channel is all ready claimed
and if the requestion channel is greater than max dma channels.
dma_enable no longer clears mode bits.   ( TODO: should document 4xx dma
usage)

Armin

[-- Attachment #2: dma_fix_0826.patch --]
[-- Type: text/plain, Size: 5058 bytes --]

# This is a BitKeeper generated patch for the following project:
# Project Name: Linux 2.4 for PowerPC development tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#	           ChangeSet	1.1140  -> 1.1141
#	arch/ppc/kernel/ppc4xx_dma.c	1.14    -> 1.15
#	include/asm-ppc/ppc4xx_dma.h	1.15    -> 1.16
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/08/26	armin@essen.mvista.com	1.1141
# fixed enable to allow more than 1 channel support pointed out by Jim Duey
# added check in enable / disable and for chan > MAX
# added in_use field in struct to make sure you can enable a chan twice
# and new return error code
# --------------------------------------------
#
diff -Nru a/arch/ppc/kernel/ppc4xx_dma.c b/arch/ppc/kernel/ppc4xx_dma.c
--- a/arch/ppc/kernel/ppc4xx_dma.c	Mon Aug 26 20:37:25 2002
+++ b/arch/ppc/kernel/ppc4xx_dma.c	Mon Aug 26 20:37:25 2002
@@ -34,6 +34,11 @@
  *
  *  Version 1.2 07/23/02 - Armin
  *  added CE to stuct in get_config
+ *
+ *  Version 1.3 08/21/02 - Armin
+ *  fixed enable to allow more than 1 channel support pointed out by
+ *  Jim Duey
+ *
  *
  */

@@ -136,8 +141,12 @@
 enable_dma(unsigned int dmanr)
 {
 	unsigned int control;
+	unsigned int tmp_cntl = 0;
 	ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr];

+	if (p_dma_ch->in_use)
+		return DMA_STATUS_CHANNEL_NOTFREE;
+
 	if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) {
 		printk("enable_dma: bad channel: %d\n", dmanr);
 		return DMA_STATUS_BAD_CHANNEL;
@@ -153,15 +162,39 @@
 		set_dst_addr(dmanr, 0);
 	}
 	/* for other xfer modes, the addresses are already set */
-	control = mfdcr(DCRN_DMACR0);
-	control &= ~(DMA_TM_MASK | DMA_TD);	/* clear all mode bits */
-	if (p_dma_ch->mode == DMA_MODE_MM) {
+		if (p_dma_ch->mode == DMA_MODE_MM) {
 		/* software initiated memory to memory */
-		control |= control | DMA_ETD_OUTPUT | DMA_TCE_ENABLE;
+		tmp_cntl |= DMA_ETD_OUTPUT | DMA_TCE_ENABLE;
 	}
-	control |= (p_dma_ch->mode | DMA_CH_ENABLE);
-	mtdcr(DCRN_DMACR0, control);
+	tmp_cntl |= (p_dma_ch->mode | DMA_CH_ENABLE);

+	switch (dmanr) {
+	case 0:
+		control = mfdcr(DCRN_DMACR0);
+		control |= tmp_cntl;
+	       	mtdcr(DCRN_DMACR0, control);
+		break;
+	case 1:
+		control = mfdcr(DCRN_DMACR1);
+		control |= tmp_cntl;
+		mtdcr(DCRN_DMACR1, control);
+		break;
+	case 2:
+		control = mfdcr(DCRN_DMACR2);
+		control |= tmp_cntl;
+		mtdcr(DCRN_DMACR2, control);
+		break;
+	case 3:
+		control = mfdcr(DCRN_DMACR3);
+		control |= tmp_cntl;
+		mtdcr(DCRN_DMACR3, control);
+		break;
+	default:
+#ifdef DEBUG_4xxDMA
+		printk("enable_dma: bad channel: %d\n", dmanr);
+#endif
+	}
+	p_dma_ch->in_use = 1;
 	return DMA_STATUS_GOOD;
 }

@@ -169,6 +202,15 @@
 disable_dma(unsigned int dmanr)
 {
 	unsigned int control;
+	ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr];
+
+	if (!p_dma_ch->in_use)
+		return DMA_STATUS_CHANNEL_NOTFREE;
+
+	if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) {
+		printk("enable_dma: bad channel: %d\n", dmanr);
+		return DMA_STATUS_BAD_CHANNEL;
+	}

 	switch (dmanr) {
 	case 0:
@@ -196,6 +238,7 @@
 		printk("disable_dma: bad channel: %d\n", dmanr);
 #endif
 	}
+	p_dma_ch->in_use = 0;
 }

 /*
@@ -348,6 +391,12 @@
 set_dma_addr(unsigned int dmanr, phys_addr_t addr)
 {
 	ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr];
+
+	if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) {
+		printk("enable_dma: bad channel: %d\n", dmanr);
+		return DMA_STATUS_BAD_CHANNEL;
+	}
+
 #ifdef DEBUG_4xxDMA
 	{
 		int error = 0;
@@ -495,7 +544,7 @@
 	unsigned int control;
 	ppc_dma_ch_t *p_dma_ch = &dma_channels[dmanr];

-	p_dma_ch->int_enable = TRUE;
+	p_dma_ch->int_enable = FALSE;
 	switch (dmanr) {
 	case 0:
 		control = mfdcr(DCRN_DMACR0);
@@ -545,11 +594,11 @@
 	DMA_MODE_READ = (unsigned long) DMA_TD;	/* Peripheral to Memory */
 	DMA_MODE_WRITE = 0;	/* Memory to Peripheral */

-#ifdef DEBUG_4xxDMA
 	if (!p_init) {
 		printk("hw_init_dma_channel: NULL p_init\n");
 		return DMA_STATUS_NULL_POINTER;
 	}
+#ifdef DEBUG_4xxDMA
 	if (dmanr >= MAX_PPC4xx_DMA_CHANNELS) {
 		printk("hw_init_dma_channel: bad channel %d\n", dmanr);
 		return DMA_STATUS_BAD_CHANNEL;
diff -Nru a/include/asm-ppc/ppc4xx_dma.h b/include/asm-ppc/ppc4xx_dma.h
--- a/include/asm-ppc/ppc4xx_dma.h	Mon Aug 26 20:37:25 2002
+++ b/include/asm-ppc/ppc4xx_dma.h	Mon Aug 26 20:37:25 2002
@@ -26,6 +26,10 @@
  *    moved scatter/gather inline code to ppc4xx_sgdma.c
  *    added three new extern proto types for the STBxxxx API's
  *
+ *    version 1.4: 08/26/02 - Armin
+ *    added in_use field for when a channel is claimed
+ *    added new return code *_NOTFREE
+ *
  */

 #ifdef __KERNEL__
@@ -57,6 +61,7 @@
 #define DMA_STATUS_OUT_OF_MEMORY	5
 #define DMA_STATUS_SGL_LIST_EMPTY	6
 #define DMA_STATUS_GENERAL_ERROR	7
+#define DMA_STATUS_CHANNEL_NOTFREE	8

 #define DMA_CHANNEL_BUSY		0x80000000

@@ -411,7 +416,9 @@
 #endif

 typedef struct {
-
+	bool in_use;	/* set when channel is being used, clr when
+			   avaliable
+			 */
 	/*
 	 * Valid polarity settings:
 	 *   DMAReq0_ActiveLow

[-- Attachment #3: dma_fix_0826.patch.gz --]
[-- Type: application/x-gunzip, Size: 1796 bytes --]

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2002-08-27  3:44 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-08-20 15:26 Question about ppc4xx_dma.h jim
2002-08-20 23:18 ` akuster
2002-08-21 19:39   ` akuster
2002-08-21 22:17     ` Todd Poynor
2002-08-22  6:18       ` akuster
2002-08-27  3:44       ` akuster

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).