aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-davinci/dma.c
diff options
context:
space:
mode:
authorSudhakar Rajashekhara <sudhakar.raj@ti.com>2010-01-06 06:59:49 -0500
committerKevin Hilman <khilman@deeprootsystems.com>2010-02-04 16:30:02 -0500
commitf900d552f95a009e4c4910aff7acbd45f952aa2e (patch)
tree8c326e61d18d65c502414c178d5dc49ca1a020a7 /arch/arm/mach-davinci/dma.c
parent447f18f1b4a3e86159353d016dcaac25414b3a42 (diff)
davinci: build list of unused EDMA events dynamically
Currently, the edma_noevent list is passed from platform data. But on some architectures, there will be many EDMA channels which will not be used at all. This patch scans all the platform devices and then builds a list of events which are not being used. The unused event list will be used to allocate EDMA channels in case of EDMA_CHANNEL_ANY usage instead of the edma_noevent being used earlier for this purpose. This patch is based on David Brownells's suggestion at http://article.gmane.org/gmane.linux.davinci/15176. Signed-off-by: Sudhakar Rajashekhara <sudhakar.raj@ti.com> Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
Diffstat (limited to 'arch/arm/mach-davinci/dma.c')
-rw-r--r--arch/arm/mach-davinci/dma.c55
1 files changed, 43 insertions, 12 deletions
diff --git a/arch/arm/mach-davinci/dma.c b/arch/arm/mach-davinci/dma.c
index 89a3dccde19f..15dd886df04c 100644
--- a/arch/arm/mach-davinci/dma.c
+++ b/arch/arm/mach-davinci/dma.c
@@ -226,11 +226,11 @@ struct edma {
226 */ 226 */
227 DECLARE_BITMAP(edma_inuse, EDMA_MAX_PARAMENTRY); 227 DECLARE_BITMAP(edma_inuse, EDMA_MAX_PARAMENTRY);
228 228
229 /* The edma_noevent bit for each channel is clear unless 229 /* The edma_unused bit for each channel is clear unless
230 * it doesn't trigger DMA events on this platform. It uses a 230 * it is not being used on this platform. It uses a bit
231 * bit of SOC-specific initialization code. 231 * of SOC-specific initialization code.
232 */ 232 */
233 DECLARE_BITMAP(edma_noevent, EDMA_MAX_DMACH); 233 DECLARE_BITMAP(edma_unused, EDMA_MAX_DMACH);
234 234
235 unsigned irq_res_start; 235 unsigned irq_res_start;
236 unsigned irq_res_end; 236 unsigned irq_res_end;
@@ -556,8 +556,27 @@ static int reserve_contiguous_slots(int ctlr, unsigned int id,
556 return EDMA_CTLR_CHAN(ctlr, i - num_slots + 1); 556 return EDMA_CTLR_CHAN(ctlr, i - num_slots + 1);
557} 557}
558 558
559static int prepare_unused_channel_list(struct device *dev, void *data)
560{
561 struct platform_device *pdev = to_platform_device(dev);
562 int i, ctlr;
563
564 for (i = 0; i < pdev->num_resources; i++) {
565 if ((pdev->resource[i].flags & IORESOURCE_DMA) &&
566 (int)pdev->resource[i].start >= 0) {
567 ctlr = EDMA_CTLR(pdev->resource[i].start);
568 clear_bit(EDMA_CHAN_SLOT(pdev->resource[i].start),
569 edma_info[ctlr]->edma_unused);
570 }
571 }
572
573 return 0;
574}
575
559/*-----------------------------------------------------------------------*/ 576/*-----------------------------------------------------------------------*/
560 577
578static bool unused_chan_list_done;
579
561/* Resource alloc/free: dma channels, parameter RAM slots */ 580/* Resource alloc/free: dma channels, parameter RAM slots */
562 581
563/** 582/**
@@ -596,6 +615,21 @@ int edma_alloc_channel(int channel,
596 enum dma_event_q eventq_no) 615 enum dma_event_q eventq_no)
597{ 616{
598 unsigned i, done = 0, ctlr = 0; 617 unsigned i, done = 0, ctlr = 0;
618 int ret = 0;
619
620 if (!unused_chan_list_done) {
621 /*
622 * Scan all the platform devices to find out the EDMA channels
623 * used and clear them in the unused list, making the rest
624 * available for ARM usage.
625 */
626 ret = bus_for_each_dev(&platform_bus_type, NULL, NULL,
627 prepare_unused_channel_list);
628 if (ret < 0)
629 return ret;
630
631 unused_chan_list_done = true;
632 }
599 633
600 if (channel >= 0) { 634 if (channel >= 0) {
601 ctlr = EDMA_CTLR(channel); 635 ctlr = EDMA_CTLR(channel);
@@ -607,7 +641,7 @@ int edma_alloc_channel(int channel,
607 channel = 0; 641 channel = 0;
608 for (;;) { 642 for (;;) {
609 channel = find_next_bit(edma_info[i]-> 643 channel = find_next_bit(edma_info[i]->
610 edma_noevent, 644 edma_unused,
611 edma_info[i]->num_channels, 645 edma_info[i]->num_channels,
612 channel); 646 channel);
613 if (channel == edma_info[i]->num_channels) 647 if (channel == edma_info[i]->num_channels)
@@ -1222,7 +1256,7 @@ int edma_start(unsigned channel)
1222 unsigned int mask = (1 << (channel & 0x1f)); 1256 unsigned int mask = (1 << (channel & 0x1f));
1223 1257
1224 /* EDMA channels without event association */ 1258 /* EDMA channels without event association */
1225 if (test_bit(channel, edma_info[ctlr]->edma_noevent)) { 1259 if (test_bit(channel, edma_info[ctlr]->edma_unused)) {
1226 pr_debug("EDMA: ESR%d %08x\n", j, 1260 pr_debug("EDMA: ESR%d %08x\n", j,
1227 edma_shadow0_read_array(ctlr, SH_ESR, j)); 1261 edma_shadow0_read_array(ctlr, SH_ESR, j));
1228 edma_shadow0_write_array(ctlr, SH_ESR, j, mask); 1262 edma_shadow0_write_array(ctlr, SH_ESR, j, mask);
@@ -1347,7 +1381,6 @@ static int __init edma_probe(struct platform_device *pdev)
1347 const s8 (*queue_tc_mapping)[2]; 1381 const s8 (*queue_tc_mapping)[2];
1348 int i, j, found = 0; 1382 int i, j, found = 0;
1349 int status = -1; 1383 int status = -1;
1350 const s8 *noevent;
1351 int irq[EDMA_MAX_CC] = {0, 0}; 1384 int irq[EDMA_MAX_CC] = {0, 0};
1352 int err_irq[EDMA_MAX_CC] = {0, 0}; 1385 int err_irq[EDMA_MAX_CC] = {0, 0};
1353 struct resource *r[EDMA_MAX_CC] = {NULL}; 1386 struct resource *r[EDMA_MAX_CC] = {NULL};
@@ -1410,11 +1443,9 @@ static int __init edma_probe(struct platform_device *pdev)
1410 memcpy_toio(edmacc_regs_base[j] + PARM_OFFSET(i), 1443 memcpy_toio(edmacc_regs_base[j] + PARM_OFFSET(i),
1411 &dummy_paramset, PARM_SIZE); 1444 &dummy_paramset, PARM_SIZE);
1412 1445
1413 noevent = info[j].noevent; 1446 /* Mark all channels as unused */
1414 if (noevent) { 1447 memset(edma_info[j]->edma_unused, 0xff,
1415 while (*noevent != -1) 1448 sizeof(edma_info[j]->edma_unused));
1416 set_bit(*noevent++, edma_info[j]->edma_noevent);
1417 }
1418 1449
1419 sprintf(irq_name, "edma%d", j); 1450 sprintf(irq_name, "edma%d", j);
1420 irq[j] = platform_get_irq_byname(pdev, irq_name); 1451 irq[j] = platform_get_irq_byname(pdev, irq_name);