diff mbox

[02/26] davinci: EDMA: restructure to support multiple channel controllers

Message ID 1246914900-9034-3-git-send-email-khilman@deeprootsystems.com (mailing list archive)
State Not Applicable
Headers show

Commit Message

Kevin Hilman July 6, 2009, 9:14 p.m. UTC
From: Sudhakar Rajashekhara <sudhakar.raj@ti.com>

Define a structure to store EDMA channel controller based information.
Use platform_device.id to find out the instance being configured in
probe function.

Signed-off-by: Sudhakar Rajashekhara <sudhakar.raj@ti.com>
Reviewed-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/mach-davinci/dm355.c             |    5 +-
 arch/arm/mach-davinci/dm644x.c            |    5 +-
 arch/arm/mach-davinci/dma.c               |  100 +++++++++++++++++++----------
 arch/arm/mach-davinci/include/mach/edma.h |    1 +
 4 files changed, 73 insertions(+), 38 deletions(-)

Comments

Kevin Hilman July 7, 2009, 5:07 p.m. UTC | #1
Russell King - ARM Linux <linux@arm.linux.org.uk> writes:

> On Mon, Jul 06, 2009 at 02:14:36PM -0700, Kevin Hilman wrote:
>> From: Sudhakar Rajashekhara <sudhakar.raj@ti.com>
>> 
>> Define a structure to store EDMA channel controller based information.
>> Use platform_device.id to find out the instance being configured in
>> probe function.
>
> Why all this complexity?  Resources are specific to each platform
> device, so just provide the _specific_ resources for each platform
> device.

Agreed.  I've asked Sudhakar to take a look at this and rework.

Thanks for the review.

Kevin
diff mbox

Patch

diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c
index baaaf32..beda643 100644
--- a/arch/arm/mach-davinci/dm355.c
+++ b/arch/arm/mach-davinci/dm355.c
@@ -563,12 +563,13 @@  static struct edma_soc_info dm355_edma_info = {
 	.n_region	= 4,
 	.n_slot		= 128,
 	.n_tc		= 2,
+	.n_cc		= 1,
 	.noevent	= dma_chan_dm355_no_event,
 };
 
 static struct resource edma_resources[] = {
 	{
-		.name	= "edma_cc",
+		.name	= "edma_cc0",
 		.start	= 0x01c00000,
 		.end	= 0x01c00000 + SZ_64K - 1,
 		.flags	= IORESOURCE_MEM,
@@ -598,7 +599,7 @@  static struct resource edma_resources[] = {
 
 static struct platform_device dm355_edma_device = {
 	.name			= "edma",
-	.id			= -1,
+	.id			= 0,
 	.dev.platform_data	= &dm355_edma_info,
 	.num_resources		= ARRAY_SIZE(edma_resources),
 	.resource		= edma_resources,
diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c
index fb5449b..ddc1d4f 100644
--- a/arch/arm/mach-davinci/dm644x.c
+++ b/arch/arm/mach-davinci/dm644x.c
@@ -489,12 +489,13 @@  static struct edma_soc_info dm644x_edma_info = {
 	.n_region	= 4,
 	.n_slot		= 128,
 	.n_tc		= 2,
+	.n_cc		= 1,
 	.noevent	= dma_chan_dm644x_no_event,
 };
 
 static struct resource edma_resources[] = {
 	{
-		.name	= "edma_cc",
+		.name	= "edma_cc0",
 		.start	= 0x01c00000,
 		.end	= 0x01c00000 + SZ_64K - 1,
 		.flags	= IORESOURCE_MEM,
@@ -524,7 +525,7 @@  static struct resource edma_resources[] = {
 
 static struct platform_device dm644x_edma_device = {
 	.name			= "edma",
-	.id			= -1,
+	.id			= 0,
 	.dev.platform_data	= &dm644x_edma_info,
 	.num_resources		= ARRAY_SIZE(edma_resources),
 	.resource		= edma_resources,
diff --git a/arch/arm/mach-davinci/dma.c b/arch/arm/mach-davinci/dma.c
index 15e9eb1..9afd55f 100644
--- a/arch/arm/mach-davinci/dma.c
+++ b/arch/arm/mach-davinci/dma.c
@@ -107,11 +107,12 @@ 
 #define EDMA_MAX_DMACH           64
 #define EDMA_MAX_PARAMENTRY     512
 #define EDMA_MAX_EVQUE            2	/* FIXME too small */
+#define EDMA_MAX_CC               2
 
 
 /*****************************************************************************/
 
-static void __iomem *edmacc_regs_base;
+static void __iomem *edmacc_regs_base[EDMA_MAX_CC];
 
 static inline unsigned int edma_read(int offset)
 {
@@ -207,25 +208,39 @@  static inline void edma_parm_or(int offset, int param_no, unsigned or)
 /*****************************************************************************/
 
 /* actual number of DMA channels and slots on this silicon */
-static unsigned num_channels;
-static unsigned num_slots;
+struct edma {
+	/* how many dma resources of each type */
+	unsigned	num_channels;
+	unsigned	num_region;
+	unsigned	num_slots;
+	unsigned	num_tc;
+	unsigned	num_cc;
+
+	/* list of channels with no even trigger; terminated by "-1" */
+	const s8	*noevent;
+
+	/* The edma_inuse bit for each PaRAM slot is clear unless the
+	 * channel is in use ... by ARM or DSP, for QDMA, or whatever.
+	 */
+	DECLARE_BITMAP(edma_inuse, EDMA_MAX_PARAMENTRY);
 
-static struct dma_interrupt_data {
-	void (*callback)(unsigned channel, unsigned short ch_status,
-			 void *data);
-	void *data;
-} intr_data[EDMA_MAX_DMACH];
+	/* The edma_noevent bit for each channel is clear unless
+	 * it doesn't trigger DMA events on this platform.  It uses a
+	 * bit of SOC-specific initialization code.
+	 */
+	DECLARE_BITMAP(edma_noevent, EDMA_MAX_DMACH);
 
-/* The edma_inuse bit for each PaRAM slot is clear unless the
- * channel is in use ... by ARM or DSP, for QDMA, or whatever.
- */
-static DECLARE_BITMAP(edma_inuse, EDMA_MAX_PARAMENTRY);
+	unsigned	irq_res_start;
+	unsigned	irq_res_end;
 
-/* The edma_noevent bit for each channel is clear unless
- * it doesn't trigger DMA events on this platform.  It uses a
- * bit of SOC-specific initialization code.
- */
-static DECLARE_BITMAP(edma_noevent, EDMA_MAX_DMACH);
+	struct dma_interrupt_data {
+		void (*callback)(unsigned channel, unsigned short ch_status,
+				void *data);
+		void *data;
+	} intr_data[EDMA_MAX_DMACH];
+};
+
+static struct edma *edma_info[EDMA_MAX_CC];
 
 /* dummy param set used to (re)initialize parameter RAM slots */
 static const struct edmacc_param dummy_paramset = {
@@ -1018,11 +1033,13 @@  static int __init edma_probe(struct platform_device *pdev)
 	int			irq = 0, err_irq = 0;
 	struct resource		*r;
 	resource_size_t		len;
+	char			name[10];
 
 	if (!info)
 		return -ENODEV;
 
-	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "edma_cc");
+	sprintf(name, "edma_cc%d", pdev->id);
+	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
 	if (!r)
 		return -ENODEV;
 
@@ -1032,28 +1049,41 @@  static int __init edma_probe(struct platform_device *pdev)
 	if (!r)
 		return -EBUSY;
 
-	edmacc_regs_base = ioremap(r->start, len);
-	if (!edmacc_regs_base) {
+	edmacc_regs_base[pdev->id] = ioremap(r->start, len);
+	if (!edmacc_regs_base[pdev->id]) {
 		status = -EBUSY;
 		goto fail1;
 	}
 
-	num_channels = min_t(unsigned, info->n_channel, EDMA_MAX_DMACH);
-	num_slots = min_t(unsigned, info->n_slot, EDMA_MAX_PARAMENTRY);
+	edma_info[pdev->id] = kmalloc(sizeof(struct edma), GFP_KERNEL);
+	if (!edma_info[pdev->id]) {
+		status = -ENOMEM;
+		iounmap(edmacc_regs_base[pdev->id]);
+		goto fail1;
+	}
+	memset(edma_info[pdev->id], 0, sizeof(struct edma));
+
+	edma_info[pdev->id]->num_channels = min_t(unsigned, info->n_channel,
+						EDMA_MAX_DMACH);
+	edma_info[pdev->id]->num_slots = min_t(unsigned, info->n_slot,
+						EDMA_MAX_PARAMENTRY);
+	edma_info[pdev->id]->num_cc = min_t(unsigned, info->n_cc, EDMA_MAX_CC);
 
-	dev_dbg(&pdev->dev, "DMA REG BASE ADDR=%p\n", edmacc_regs_base);
+	dev_dbg(&pdev->dev, "DMA REG BASE ADDR=%p\n",
+		edmacc_regs_base[pdev->id]);
 
-	for (i = 0; i < num_slots; i++)
-		memcpy_toio(edmacc_regs_base + PARM_OFFSET(i),
+	for (i = 0; i < edma_info[pdev->id]->num_slots; i++)
+		memcpy_toio(edmacc_regs_base[pdev->id] + PARM_OFFSET(i),
 				&dummy_paramset, PARM_SIZE);
 
 	noevent = info->noevent;
 	if (noevent) {
 		while (*noevent != -1)
-			set_bit(*noevent++, edma_noevent);
+			set_bit(*noevent++, edma_info[pdev->id]->edma_noevent);
 	}
 
 	irq = platform_get_irq(pdev, 0);
+	edma_info[pdev->id]->irq_res_start = irq;
 	status = request_irq(irq, dma_irq_handler, 0, "edma", &pdev->dev);
 	if (status < 0) {
 		dev_dbg(&pdev->dev, "request_irq %d failed --> %d\n",
@@ -1062,6 +1092,7 @@  static int __init edma_probe(struct platform_device *pdev)
 	}
 
 	err_irq = platform_get_irq(pdev, 1);
+	edma_info[pdev->id]->irq_res_end = err_irq;
 	status = request_irq(err_irq, dma_ccerr_handler, 0,
 				"edma_error", &pdev->dev);
 	if (status < 0) {
@@ -1091,22 +1122,23 @@  static int __init edma_probe(struct platform_device *pdev)
 	 * This way, long transfers on the low priority queue
 	 * started by the codec engine will not cause audio defects.
 	 */
-	for (i = 0; i < num_channels; i++)
-		map_dmach_queue(i, EVENTQ_1);
+	for (i = 0; i < edma_info[pdev->id]->num_channels; i++)
+		map_dmach_queue(pdev->id, i, EVENTQ_1);
 
 	/* Event queue to TC mapping */
 	for (i = 0; queue_tc_mapping[i][0] != -1; i++)
-		map_queue_tc(queue_tc_mapping[i][0], queue_tc_mapping[i][1]);
+		map_queue_tc(pdev->id, queue_tc_mapping[i][0],
+				queue_tc_mapping[i][1]);
 
 	/* Event queue priority mapping */
 	for (i = 0; queue_priority_mapping[i][0] != -1; i++)
-		assign_priority_to_queue(queue_priority_mapping[i][0],
+		assign_priority_to_queue(pdev->id, queue_priority_mapping[i][0],
 					 queue_priority_mapping[i][1]);
 
 	for (i = 0; i < info->n_region; i++) {
-		edma_write_array2(EDMA_DRAE, i, 0, 0x0);
-		edma_write_array2(EDMA_DRAE, i, 1, 0x0);
-		edma_write_array(EDMA_QRAE, i, 0x0);
+		edma_write_array2(pdev->id, EDMA_DRAE, i, 0, 0x0);
+		edma_write_array2(pdev->id, EDMA_DRAE, i, 1, 0x0);
+		edma_write_array(pdev->id, EDMA_QRAE, i, 0x0);
 	}
 
 	return 0;
@@ -1116,7 +1148,7 @@  fail:
 		free_irq(err_irq, NULL);
 	if (irq)
 		free_irq(irq, NULL);
-	iounmap(edmacc_regs_base);
+	iounmap(edmacc_regs_base[pdev->id]);
 fail1:
 	release_mem_region(r->start, len);
 	return status;
diff --git a/arch/arm/mach-davinci/include/mach/edma.h b/arch/arm/mach-davinci/include/mach/edma.h
index 24a3792..0780a4e 100644
--- a/arch/arm/mach-davinci/include/mach/edma.h
+++ b/arch/arm/mach-davinci/include/mach/edma.h
@@ -216,6 +216,7 @@  struct edma_soc_info {
 	unsigned	n_region;
 	unsigned	n_slot;
 	unsigned	n_tc;
+	unsigned	n_cc;
 
 	/* list of channels with no even trigger; terminated by "-1" */
 	const s8	*noevent;