diff options
Diffstat (limited to 'arch/arm/mach-davinci/dma.c')
| -rw-r--r-- | arch/arm/mach-davinci/dma.c | 55 |
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 | ||
| 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); |
