diff options
-rw-r--r-- | drivers/dma/edma.c | 159 |
1 files changed, 151 insertions, 8 deletions
diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c index 183ec85cb6ca..592f3be8b435 100644 --- a/drivers/dma/edma.c +++ b/drivers/dma/edma.c | |||
@@ -60,6 +60,7 @@ | |||
60 | struct edma_desc { | 60 | struct edma_desc { |
61 | struct virt_dma_desc vdesc; | 61 | struct virt_dma_desc vdesc; |
62 | struct list_head node; | 62 | struct list_head node; |
63 | int cyclic; | ||
63 | int absync; | 64 | int absync; |
64 | int pset_nr; | 65 | int pset_nr; |
65 | int processed; | 66 | int processed; |
@@ -173,8 +174,13 @@ static void edma_execute(struct edma_chan *echan) | |||
173 | * then setup a link to the dummy slot, this results in all future | 174 | * then setup a link to the dummy slot, this results in all future |
174 | * events being absorbed and that's OK because we're done | 175 | * events being absorbed and that's OK because we're done |
175 | */ | 176 | */ |
176 | if (edesc->processed == edesc->pset_nr) | 177 | if (edesc->processed == edesc->pset_nr) { |
177 | edma_link(echan->slot[nslots-1], echan->ecc->dummy_slot); | 178 | if (edesc->cyclic) |
179 | edma_link(echan->slot[nslots-1], echan->slot[1]); | ||
180 | else | ||
181 | edma_link(echan->slot[nslots-1], | ||
182 | echan->ecc->dummy_slot); | ||
183 | } | ||
178 | 184 | ||
179 | edma_resume(echan->ch_num); | 185 | edma_resume(echan->ch_num); |
180 | 186 | ||
@@ -459,6 +465,138 @@ static struct dma_async_tx_descriptor *edma_prep_slave_sg( | |||
459 | return vchan_tx_prep(&echan->vchan, &edesc->vdesc, tx_flags); | 465 | return vchan_tx_prep(&echan->vchan, &edesc->vdesc, tx_flags); |
460 | } | 466 | } |
461 | 467 | ||
468 | static struct dma_async_tx_descriptor *edma_prep_dma_cyclic( | ||
469 | struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, | ||
470 | size_t period_len, enum dma_transfer_direction direction, | ||
471 | unsigned long tx_flags, void *context) | ||
472 | { | ||
473 | struct edma_chan *echan = to_edma_chan(chan); | ||
474 | struct device *dev = chan->device->dev; | ||
475 | struct edma_desc *edesc; | ||
476 | dma_addr_t src_addr, dst_addr; | ||
477 | enum dma_slave_buswidth dev_width; | ||
478 | u32 burst; | ||
479 | int i, ret, nslots; | ||
480 | |||
481 | if (unlikely(!echan || !buf_len || !period_len)) | ||
482 | return NULL; | ||
483 | |||
484 | if (direction == DMA_DEV_TO_MEM) { | ||
485 | src_addr = echan->cfg.src_addr; | ||
486 | dst_addr = buf_addr; | ||
487 | dev_width = echan->cfg.src_addr_width; | ||
488 | burst = echan->cfg.src_maxburst; | ||
489 | } else if (direction == DMA_MEM_TO_DEV) { | ||
490 | src_addr = buf_addr; | ||
491 | dst_addr = echan->cfg.dst_addr; | ||
492 | dev_width = echan->cfg.dst_addr_width; | ||
493 | burst = echan->cfg.dst_maxburst; | ||
494 | } else { | ||
495 | dev_err(dev, "%s: bad direction?\n", __func__); | ||
496 | return NULL; | ||
497 | } | ||
498 | |||
499 | if (dev_width == DMA_SLAVE_BUSWIDTH_UNDEFINED) { | ||
500 | dev_err(dev, "Undefined slave buswidth\n"); | ||
501 | return NULL; | ||
502 | } | ||
503 | |||
504 | if (unlikely(buf_len % period_len)) { | ||
505 | dev_err(dev, "Period should be multiple of Buffer length\n"); | ||
506 | return NULL; | ||
507 | } | ||
508 | |||
509 | nslots = (buf_len / period_len) + 1; | ||
510 | |||
511 | /* | ||
512 | * Cyclic DMA users such as audio cannot tolerate delays introduced | ||
513 | * by cases where the number of periods is more than the maximum | ||
514 | * number of SGs the EDMA driver can handle at a time. For DMA types | ||
515 | * such as Slave SGs, such delays are tolerable and synchronized, | ||
516 | * but the synchronization is difficult to achieve with Cyclic and | ||
517 | * cannot be guaranteed, so we error out early. | ||
518 | */ | ||
519 | if (nslots > MAX_NR_SG) | ||
520 | return NULL; | ||
521 | |||
522 | edesc = kzalloc(sizeof(*edesc) + nslots * | ||
523 | sizeof(edesc->pset[0]), GFP_ATOMIC); | ||
524 | if (!edesc) { | ||
525 | dev_dbg(dev, "Failed to allocate a descriptor\n"); | ||
526 | return NULL; | ||
527 | } | ||
528 | |||
529 | edesc->cyclic = 1; | ||
530 | edesc->pset_nr = nslots; | ||
531 | |||
532 | dev_dbg(dev, "%s: nslots=%d\n", __func__, nslots); | ||
533 | dev_dbg(dev, "%s: period_len=%d\n", __func__, period_len); | ||
534 | dev_dbg(dev, "%s: buf_len=%d\n", __func__, buf_len); | ||
535 | |||
536 | for (i = 0; i < nslots; i++) { | ||
537 | /* Allocate a PaRAM slot, if needed */ | ||
538 | if (echan->slot[i] < 0) { | ||
539 | echan->slot[i] = | ||
540 | edma_alloc_slot(EDMA_CTLR(echan->ch_num), | ||
541 | EDMA_SLOT_ANY); | ||
542 | if (echan->slot[i] < 0) { | ||
543 | dev_err(dev, "Failed to allocate slot\n"); | ||
544 | return NULL; | ||
545 | } | ||
546 | } | ||
547 | |||
548 | if (i == nslots - 1) { | ||
549 | memcpy(&edesc->pset[i], &edesc->pset[0], | ||
550 | sizeof(edesc->pset[0])); | ||
551 | break; | ||
552 | } | ||
553 | |||
554 | ret = edma_config_pset(chan, &edesc->pset[i], src_addr, | ||
555 | dst_addr, burst, dev_width, period_len, | ||
556 | direction); | ||
557 | if (ret < 0) | ||
558 | return NULL; | ||
559 | |||
560 | if (direction == DMA_DEV_TO_MEM) | ||
561 | dst_addr += period_len; | ||
562 | else | ||
563 | src_addr += period_len; | ||
564 | |||
565 | dev_dbg(dev, "%s: Configure period %d of buf:\n", __func__, i); | ||
566 | dev_dbg(dev, | ||
567 | "\n pset[%d]:\n" | ||
568 | " chnum\t%d\n" | ||
569 | " slot\t%d\n" | ||
570 | " opt\t%08x\n" | ||
571 | " src\t%08x\n" | ||
572 | " dst\t%08x\n" | ||
573 | " abcnt\t%08x\n" | ||
574 | " ccnt\t%08x\n" | ||
575 | " bidx\t%08x\n" | ||
576 | " cidx\t%08x\n" | ||
577 | " lkrld\t%08x\n", | ||
578 | i, echan->ch_num, echan->slot[i], | ||
579 | edesc->pset[i].opt, | ||
580 | edesc->pset[i].src, | ||
581 | edesc->pset[i].dst, | ||
582 | edesc->pset[i].a_b_cnt, | ||
583 | edesc->pset[i].ccnt, | ||
584 | edesc->pset[i].src_dst_bidx, | ||
585 | edesc->pset[i].src_dst_cidx, | ||
586 | edesc->pset[i].link_bcntrld); | ||
587 | |||
588 | edesc->absync = ret; | ||
589 | |||
590 | /* | ||
591 | * Enable interrupts for every period because callback | ||
592 | * has to be called for every period. | ||
593 | */ | ||
594 | edesc->pset[i].opt |= TCINTEN; | ||
595 | } | ||
596 | |||
597 | return vchan_tx_prep(&echan->vchan, &edesc->vdesc, tx_flags); | ||
598 | } | ||
599 | |||
462 | static void edma_callback(unsigned ch_num, u16 ch_status, void *data) | 600 | static void edma_callback(unsigned ch_num, u16 ch_status, void *data) |
463 | { | 601 | { |
464 | struct edma_chan *echan = data; | 602 | struct edma_chan *echan = data; |
@@ -467,24 +605,28 @@ static void edma_callback(unsigned ch_num, u16 ch_status, void *data) | |||
467 | unsigned long flags; | 605 | unsigned long flags; |
468 | struct edmacc_param p; | 606 | struct edmacc_param p; |
469 | 607 | ||
470 | /* Pause the channel */ | 608 | edesc = echan->edesc; |
471 | edma_pause(echan->ch_num); | 609 | |
610 | /* Pause the channel for non-cyclic */ | ||
611 | if (!edesc || (edesc && !edesc->cyclic)) | ||
612 | edma_pause(echan->ch_num); | ||
472 | 613 | ||
473 | switch (ch_status) { | 614 | switch (ch_status) { |
474 | case EDMA_DMA_COMPLETE: | 615 | case EDMA_DMA_COMPLETE: |
475 | spin_lock_irqsave(&echan->vchan.lock, flags); | 616 | spin_lock_irqsave(&echan->vchan.lock, flags); |
476 | 617 | ||
477 | edesc = echan->edesc; | ||
478 | if (edesc) { | 618 | if (edesc) { |
479 | if (edesc->processed == edesc->pset_nr) { | 619 | if (edesc->cyclic) { |
620 | vchan_cyclic_callback(&edesc->vdesc); | ||
621 | } else if (edesc->processed == edesc->pset_nr) { | ||
480 | dev_dbg(dev, "Transfer complete, stopping channel %d\n", ch_num); | 622 | dev_dbg(dev, "Transfer complete, stopping channel %d\n", ch_num); |
481 | edma_stop(echan->ch_num); | 623 | edma_stop(echan->ch_num); |
482 | vchan_cookie_complete(&edesc->vdesc); | 624 | vchan_cookie_complete(&edesc->vdesc); |
625 | edma_execute(echan); | ||
483 | } else { | 626 | } else { |
484 | dev_dbg(dev, "Intermediate transfer complete on channel %d\n", ch_num); | 627 | dev_dbg(dev, "Intermediate transfer complete on channel %d\n", ch_num); |
628 | edma_execute(echan); | ||
485 | } | 629 | } |
486 | |||
487 | edma_execute(echan); | ||
488 | } | 630 | } |
489 | 631 | ||
490 | spin_unlock_irqrestore(&echan->vchan.lock, flags); | 632 | spin_unlock_irqrestore(&echan->vchan.lock, flags); |
@@ -680,6 +822,7 @@ static void edma_dma_init(struct edma_cc *ecc, struct dma_device *dma, | |||
680 | struct device *dev) | 822 | struct device *dev) |
681 | { | 823 | { |
682 | dma->device_prep_slave_sg = edma_prep_slave_sg; | 824 | dma->device_prep_slave_sg = edma_prep_slave_sg; |
825 | dma->device_prep_dma_cyclic = edma_prep_dma_cyclic; | ||
683 | dma->device_alloc_chan_resources = edma_alloc_chan_resources; | 826 | dma->device_alloc_chan_resources = edma_alloc_chan_resources; |
684 | dma->device_free_chan_resources = edma_free_chan_resources; | 827 | dma->device_free_chan_resources = edma_free_chan_resources; |
685 | dma->device_issue_pending = edma_issue_pending; | 828 | dma->device_issue_pending = edma_issue_pending; |