diff options
author | Sudhakar Rajashekhara <sudhakar.raj@ti.com> | 2010-01-06 06:59:49 -0500 |
---|---|---|
committer | Kevin Hilman <khilman@deeprootsystems.com> | 2010-02-04 16:30:02 -0500 |
commit | f900d552f95a009e4c4910aff7acbd45f952aa2e (patch) | |
tree | 8c326e61d18d65c502414c178d5dc49ca1a020a7 | |
parent | 447f18f1b4a3e86159353d016dcaac25414b3a42 (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>
-rw-r--r-- | arch/arm/mach-davinci/devices-da8xx.c | 6 | ||||
-rw-r--r-- | arch/arm/mach-davinci/dm355.c | 8 | ||||
-rw-r--r-- | arch/arm/mach-davinci/dm644x.c | 10 | ||||
-rw-r--r-- | arch/arm/mach-davinci/dm646x.c | 9 | ||||
-rw-r--r-- | arch/arm/mach-davinci/dma.c | 55 | ||||
-rw-r--r-- | arch/arm/mach-davinci/include/mach/edma.h | 2 |
6 files changed, 43 insertions, 47 deletions
diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c index 0c759ad0aeee..ab12a8f0d75d 100644 --- a/arch/arm/mach-davinci/devices-da8xx.c +++ b/arch/arm/mach-davinci/devices-da8xx.c | |||
@@ -83,11 +83,6 @@ struct platform_device da8xx_serial_device = { | |||
83 | }, | 83 | }, |
84 | }; | 84 | }; |
85 | 85 | ||
86 | static const s8 da8xx_dma_chan_no_event[] = { | ||
87 | 20, 21, | ||
88 | -1 | ||
89 | }; | ||
90 | |||
91 | static const s8 da8xx_queue_tc_mapping[][2] = { | 86 | static const s8 da8xx_queue_tc_mapping[][2] = { |
92 | /* {event queue no, TC no} */ | 87 | /* {event queue no, TC no} */ |
93 | {0, 0}, | 88 | {0, 0}, |
@@ -109,7 +104,6 @@ static struct edma_soc_info da8xx_edma_info[] = { | |||
109 | .n_slot = 128, | 104 | .n_slot = 128, |
110 | .n_tc = 2, | 105 | .n_tc = 2, |
111 | .n_cc = 1, | 106 | .n_cc = 1, |
112 | .noevent = da8xx_dma_chan_no_event, | ||
113 | .queue_tc_mapping = da8xx_queue_tc_mapping, | 107 | .queue_tc_mapping = da8xx_queue_tc_mapping, |
114 | .queue_priority_mapping = da8xx_queue_priority_mapping, | 108 | .queue_priority_mapping = da8xx_queue_priority_mapping, |
115 | }, | 109 | }, |
diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c index dedf4d4f3a27..b1185f82ffb3 100644 --- a/arch/arm/mach-davinci/dm355.c +++ b/arch/arm/mach-davinci/dm355.c | |||
@@ -564,13 +564,6 @@ static u8 dm355_default_priorities[DAVINCI_N_AINTC_IRQ] = { | |||
564 | 564 | ||
565 | /*----------------------------------------------------------------------*/ | 565 | /*----------------------------------------------------------------------*/ |
566 | 566 | ||
567 | static const s8 dma_chan_dm355_no_event[] = { | ||
568 | 12, 13, 24, 56, 57, | ||
569 | 58, 59, 60, 61, 62, | ||
570 | 63, | ||
571 | -1 | ||
572 | }; | ||
573 | |||
574 | static const s8 | 567 | static const s8 |
575 | queue_tc_mapping[][2] = { | 568 | queue_tc_mapping[][2] = { |
576 | /* {event queue no, TC no} */ | 569 | /* {event queue no, TC no} */ |
@@ -594,7 +587,6 @@ static struct edma_soc_info dm355_edma_info[] = { | |||
594 | .n_slot = 128, | 587 | .n_slot = 128, |
595 | .n_tc = 2, | 588 | .n_tc = 2, |
596 | .n_cc = 1, | 589 | .n_cc = 1, |
597 | .noevent = dma_chan_dm355_no_event, | ||
598 | .queue_tc_mapping = queue_tc_mapping, | 590 | .queue_tc_mapping = queue_tc_mapping, |
599 | .queue_priority_mapping = queue_priority_mapping, | 591 | .queue_priority_mapping = queue_priority_mapping, |
600 | }, | 592 | }, |
diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c index 2cd008156dea..fc060e7aefdf 100644 --- a/arch/arm/mach-davinci/dm644x.c +++ b/arch/arm/mach-davinci/dm644x.c | |||
@@ -479,15 +479,6 @@ static u8 dm644x_default_priorities[DAVINCI_N_AINTC_IRQ] = { | |||
479 | 479 | ||
480 | /*----------------------------------------------------------------------*/ | 480 | /*----------------------------------------------------------------------*/ |
481 | 481 | ||
482 | static const s8 dma_chan_dm644x_no_event[] = { | ||
483 | 0, 1, 12, 13, 14, | ||
484 | 15, 25, 30, 31, 45, | ||
485 | 46, 47, 55, 56, 57, | ||
486 | 58, 59, 60, 61, 62, | ||
487 | 63, | ||
488 | -1 | ||
489 | }; | ||
490 | |||
491 | static const s8 | 482 | static const s8 |
492 | queue_tc_mapping[][2] = { | 483 | queue_tc_mapping[][2] = { |
493 | /* {event queue no, TC no} */ | 484 | /* {event queue no, TC no} */ |
@@ -511,7 +502,6 @@ static struct edma_soc_info dm644x_edma_info[] = { | |||
511 | .n_slot = 128, | 502 | .n_slot = 128, |
512 | .n_tc = 2, | 503 | .n_tc = 2, |
513 | .n_cc = 1, | 504 | .n_cc = 1, |
514 | .noevent = dma_chan_dm644x_no_event, | ||
515 | .queue_tc_mapping = queue_tc_mapping, | 505 | .queue_tc_mapping = queue_tc_mapping, |
516 | .queue_priority_mapping = queue_priority_mapping, | 506 | .queue_priority_mapping = queue_priority_mapping, |
517 | }, | 507 | }, |
diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c index 515d3edb9a33..7eb34e9253c6 100644 --- a/arch/arm/mach-davinci/dm646x.c +++ b/arch/arm/mach-davinci/dm646x.c | |||
@@ -511,14 +511,6 @@ static u8 dm646x_default_priorities[DAVINCI_N_AINTC_IRQ] = { | |||
511 | 511 | ||
512 | /*----------------------------------------------------------------------*/ | 512 | /*----------------------------------------------------------------------*/ |
513 | 513 | ||
514 | static const s8 dma_chan_dm646x_no_event[] = { | ||
515 | 0, 1, 2, 3, 13, | ||
516 | 14, 15, 24, 25, 26, | ||
517 | 27, 30, 31, 54, 55, | ||
518 | 56, | ||
519 | -1 | ||
520 | }; | ||
521 | |||
522 | /* Four Transfer Controllers on DM646x */ | 514 | /* Four Transfer Controllers on DM646x */ |
523 | static const s8 | 515 | static const s8 |
524 | dm646x_queue_tc_mapping[][2] = { | 516 | dm646x_queue_tc_mapping[][2] = { |
@@ -547,7 +539,6 @@ static struct edma_soc_info dm646x_edma_info[] = { | |||
547 | .n_slot = 512, | 539 | .n_slot = 512, |
548 | .n_tc = 4, | 540 | .n_tc = 4, |
549 | .n_cc = 1, | 541 | .n_cc = 1, |
550 | .noevent = dma_chan_dm646x_no_event, | ||
551 | .queue_tc_mapping = dm646x_queue_tc_mapping, | 542 | .queue_tc_mapping = dm646x_queue_tc_mapping, |
552 | .queue_priority_mapping = dm646x_queue_priority_mapping, | 543 | .queue_priority_mapping = dm646x_queue_priority_mapping, |
553 | }, | 544 | }, |
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 | ||
559 | static 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 | ||
578 | static 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); |
diff --git a/arch/arm/mach-davinci/include/mach/edma.h b/arch/arm/mach-davinci/include/mach/edma.h index eb8bfd7925e7..ced3092af5ba 100644 --- a/arch/arm/mach-davinci/include/mach/edma.h +++ b/arch/arm/mach-davinci/include/mach/edma.h | |||
@@ -280,8 +280,6 @@ struct edma_soc_info { | |||
280 | unsigned n_cc; | 280 | unsigned n_cc; |
281 | enum dma_event_q default_queue; | 281 | enum dma_event_q default_queue; |
282 | 282 | ||
283 | /* list of channels with no even trigger; terminated by "-1" */ | ||
284 | const s8 *noevent; | ||
285 | const s8 (*queue_tc_mapping)[2]; | 283 | const s8 (*queue_tc_mapping)[2]; |
286 | const s8 (*queue_priority_mapping)[2]; | 284 | const s8 (*queue_priority_mapping)[2]; |
287 | }; | 285 | }; |