diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-03-01 16:05:40 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-03-01 16:05:40 -0500 |
commit | 13dda80e48439b446d0bc9bab34b91484bc8f533 (patch) | |
tree | e8037122d65fe2a5dd8f633a7648b2597640a2ce /arch/arm/mach-davinci/dma.c | |
parent | 379e3a820da171cb1d97e8dccd736a69cebfb7c0 (diff) | |
parent | 5f19daa16ffca55db5b0253eba2bd0f71ee7f7f4 (diff) |
Merge branch 'davinci-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-davinci
* 'davinci-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-davinci: (40 commits)
DaVinci DM365: Adding support for SPI EEPROM
DaVinci DM365: Adding DM365 SPI support
DaVinci DM355: Modifications to DM355 SPI support
DaVinci: SPI: Adding header file for SPI support.
davinci: dm646x: CDCE clocks: davinci_clk converted to clk_lookup
davinci: clkdev cleanup: remove clk_lookup wrapper, use clkdev_add_table()
DaVinci: DM365: Voice codec support for the DM365 SoC
davinci: clock: let clk->set_rate function sleep
Add SDA and SCL pin numbers to i2c platform data
davinci: da8xx/omap-l1xx: Add EDMA platform data for da850/omap-l138
davinci: build list of unused EDMA events dynamically
davinci: Fix edma_alloc_channel api for EDMA_CHANNEL_ANY case
davinci: Keep count of channel controllers on a platform
davinci: Correct return value of edma_alloc_channel api
davinci: add CDCE949 support on DM6467 EVM
davinci: add support for CDCE949 clock synthesizer
davinci: da850/omap-l138 EVM: register for suspend support
davinci: da850/omap-l138: add support for SoC suspend
davinci: add power management support
DaVinci: DM365: Changing default queue for DM365.
...
Diffstat (limited to 'arch/arm/mach-davinci/dma.c')
-rw-r--r-- | arch/arm/mach-davinci/dma.c | 67 |
1 files changed, 51 insertions, 16 deletions
diff --git a/arch/arm/mach-davinci/dma.c b/arch/arm/mach-davinci/dma.c index 648fbb760ae1..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; |
@@ -243,6 +243,7 @@ struct edma { | |||
243 | }; | 243 | }; |
244 | 244 | ||
245 | static struct edma *edma_info[EDMA_MAX_CC]; | 245 | static struct edma *edma_info[EDMA_MAX_CC]; |
246 | static int arch_num_cc; | ||
246 | 247 | ||
247 | /* dummy param set used to (re)initialize parameter RAM slots */ | 248 | /* dummy param set used to (re)initialize parameter RAM slots */ |
248 | static const struct edmacc_param dummy_paramset = { | 249 | static const struct edmacc_param dummy_paramset = { |
@@ -555,8 +556,27 @@ static int reserve_contiguous_slots(int ctlr, unsigned int id, | |||
555 | return EDMA_CTLR_CHAN(ctlr, i - num_slots + 1); | 556 | return EDMA_CTLR_CHAN(ctlr, i - num_slots + 1); |
556 | } | 557 | } |
557 | 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 | |||
558 | /*-----------------------------------------------------------------------*/ | 576 | /*-----------------------------------------------------------------------*/ |
559 | 577 | ||
578 | static bool unused_chan_list_done; | ||
579 | |||
560 | /* Resource alloc/free: dma channels, parameter RAM slots */ | 580 | /* Resource alloc/free: dma channels, parameter RAM slots */ |
561 | 581 | ||
562 | /** | 582 | /** |
@@ -594,7 +614,22 @@ int edma_alloc_channel(int channel, | |||
594 | void *data, | 614 | void *data, |
595 | enum dma_event_q eventq_no) | 615 | enum dma_event_q eventq_no) |
596 | { | 616 | { |
597 | unsigned i, done, 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 | } | ||
598 | 633 | ||
599 | if (channel >= 0) { | 634 | if (channel >= 0) { |
600 | ctlr = EDMA_CTLR(channel); | 635 | ctlr = EDMA_CTLR(channel); |
@@ -602,15 +637,15 @@ int edma_alloc_channel(int channel, | |||
602 | } | 637 | } |
603 | 638 | ||
604 | if (channel < 0) { | 639 | if (channel < 0) { |
605 | for (i = 0; i < EDMA_MAX_CC; i++) { | 640 | for (i = 0; i < arch_num_cc; i++) { |
606 | channel = 0; | 641 | channel = 0; |
607 | for (;;) { | 642 | for (;;) { |
608 | channel = find_next_bit(edma_info[i]-> | 643 | channel = find_next_bit(edma_info[i]-> |
609 | edma_noevent, | 644 | edma_unused, |
610 | edma_info[i]->num_channels, | 645 | edma_info[i]->num_channels, |
611 | channel); | 646 | channel); |
612 | if (channel == edma_info[i]->num_channels) | 647 | if (channel == edma_info[i]->num_channels) |
613 | return -ENOMEM; | 648 | break; |
614 | if (!test_and_set_bit(channel, | 649 | if (!test_and_set_bit(channel, |
615 | edma_info[i]->edma_inuse)) { | 650 | edma_info[i]->edma_inuse)) { |
616 | done = 1; | 651 | done = 1; |
@@ -622,6 +657,8 @@ int edma_alloc_channel(int channel, | |||
622 | if (done) | 657 | if (done) |
623 | break; | 658 | break; |
624 | } | 659 | } |
660 | if (!done) | ||
661 | return -ENOMEM; | ||
625 | } else if (channel >= edma_info[ctlr]->num_channels) { | 662 | } else if (channel >= edma_info[ctlr]->num_channels) { |
626 | return -EINVAL; | 663 | return -EINVAL; |
627 | } else if (test_and_set_bit(channel, edma_info[ctlr]->edma_inuse)) { | 664 | } else if (test_and_set_bit(channel, edma_info[ctlr]->edma_inuse)) { |
@@ -642,7 +679,7 @@ int edma_alloc_channel(int channel, | |||
642 | 679 | ||
643 | map_dmach_queue(ctlr, channel, eventq_no); | 680 | map_dmach_queue(ctlr, channel, eventq_no); |
644 | 681 | ||
645 | return channel; | 682 | return EDMA_CTLR_CHAN(ctlr, channel); |
646 | } | 683 | } |
647 | EXPORT_SYMBOL(edma_alloc_channel); | 684 | EXPORT_SYMBOL(edma_alloc_channel); |
648 | 685 | ||
@@ -1219,7 +1256,7 @@ int edma_start(unsigned channel) | |||
1219 | unsigned int mask = (1 << (channel & 0x1f)); | 1256 | unsigned int mask = (1 << (channel & 0x1f)); |
1220 | 1257 | ||
1221 | /* EDMA channels without event association */ | 1258 | /* EDMA channels without event association */ |
1222 | if (test_bit(channel, edma_info[ctlr]->edma_noevent)) { | 1259 | if (test_bit(channel, edma_info[ctlr]->edma_unused)) { |
1223 | pr_debug("EDMA: ESR%d %08x\n", j, | 1260 | pr_debug("EDMA: ESR%d %08x\n", j, |
1224 | edma_shadow0_read_array(ctlr, SH_ESR, j)); | 1261 | edma_shadow0_read_array(ctlr, SH_ESR, j)); |
1225 | edma_shadow0_write_array(ctlr, SH_ESR, j, mask); | 1262 | edma_shadow0_write_array(ctlr, SH_ESR, j, mask); |
@@ -1344,7 +1381,6 @@ static int __init edma_probe(struct platform_device *pdev) | |||
1344 | const s8 (*queue_tc_mapping)[2]; | 1381 | const s8 (*queue_tc_mapping)[2]; |
1345 | int i, j, found = 0; | 1382 | int i, j, found = 0; |
1346 | int status = -1; | 1383 | int status = -1; |
1347 | const s8 *noevent; | ||
1348 | int irq[EDMA_MAX_CC] = {0, 0}; | 1384 | int irq[EDMA_MAX_CC] = {0, 0}; |
1349 | int err_irq[EDMA_MAX_CC] = {0, 0}; | 1385 | int err_irq[EDMA_MAX_CC] = {0, 0}; |
1350 | struct resource *r[EDMA_MAX_CC] = {NULL}; | 1386 | struct resource *r[EDMA_MAX_CC] = {NULL}; |
@@ -1407,11 +1443,9 @@ static int __init edma_probe(struct platform_device *pdev) | |||
1407 | memcpy_toio(edmacc_regs_base[j] + PARM_OFFSET(i), | 1443 | memcpy_toio(edmacc_regs_base[j] + PARM_OFFSET(i), |
1408 | &dummy_paramset, PARM_SIZE); | 1444 | &dummy_paramset, PARM_SIZE); |
1409 | 1445 | ||
1410 | noevent = info[j].noevent; | 1446 | /* Mark all channels as unused */ |
1411 | if (noevent) { | 1447 | memset(edma_info[j]->edma_unused, 0xff, |
1412 | while (*noevent != -1) | 1448 | sizeof(edma_info[j]->edma_unused)); |
1413 | set_bit(*noevent++, edma_info[j]->edma_noevent); | ||
1414 | } | ||
1415 | 1449 | ||
1416 | sprintf(irq_name, "edma%d", j); | 1450 | sprintf(irq_name, "edma%d", j); |
1417 | irq[j] = platform_get_irq_byname(pdev, irq_name); | 1451 | irq[j] = platform_get_irq_byname(pdev, irq_name); |
@@ -1467,6 +1501,7 @@ static int __init edma_probe(struct platform_device *pdev) | |||
1467 | edma_write_array2(j, EDMA_DRAE, i, 1, 0x0); | 1501 | edma_write_array2(j, EDMA_DRAE, i, 1, 0x0); |
1468 | edma_write_array(j, EDMA_QRAE, i, 0x0); | 1502 | edma_write_array(j, EDMA_QRAE, i, 0x0); |
1469 | } | 1503 | } |
1504 | arch_num_cc++; | ||
1470 | } | 1505 | } |
1471 | 1506 | ||
1472 | if (tc_errs_handled) { | 1507 | if (tc_errs_handled) { |