diff options
author | Martin Sperl <kernel@martin.sperl.org> | 2016-03-16 15:25:02 -0400 |
---|---|---|
committer | Vinod Koul <vinod.koul@intel.com> | 2016-04-15 00:27:22 -0400 |
commit | d9f094a02f30510ec5d394c44d01d2ec187d7e45 (patch) | |
tree | aa46cf8b333fb228c11e42d425f0ce5788ab2ed9 /drivers/dma/bcm2835-dma.c | |
parent | 388cc7a281c06e484afcc3c5125b3271316209ef (diff) |
dmaengine: bcm2835: add dma_memcopy support to bcm2835-dma
Also added check for an error condition in bcm2835_dma_create_cb_chain
that showed up during development of this patch.
Tested using dmatest for all enabled channels.
Signed-off-by: Martin Sperl <kernel@martin.sperl.org>
Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Diffstat (limited to 'drivers/dma/bcm2835-dma.c')
-rw-r--r-- | drivers/dma/bcm2835-dma.c | 36 |
1 files changed, 35 insertions, 1 deletions
diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c index b46b12f66f38..cc771cd35dd0 100644 --- a/drivers/dma/bcm2835-dma.c +++ b/drivers/dma/bcm2835-dma.c | |||
@@ -310,6 +310,9 @@ static struct bcm2835_desc *bcm2835_dma_create_cb_chain( | |||
310 | struct bcm2835_cb_entry *cb_entry; | 310 | struct bcm2835_cb_entry *cb_entry; |
311 | struct bcm2835_dma_cb *control_block; | 311 | struct bcm2835_dma_cb *control_block; |
312 | 312 | ||
313 | if (!frames) | ||
314 | return NULL; | ||
315 | |||
313 | /* allocate and setup the descriptor. */ | 316 | /* allocate and setup the descriptor. */ |
314 | d = kzalloc(sizeof(*d) + frames * sizeof(struct bcm2835_cb_entry), | 317 | d = kzalloc(sizeof(*d) + frames * sizeof(struct bcm2835_cb_entry), |
315 | gfp); | 318 | gfp); |
@@ -597,6 +600,34 @@ static void bcm2835_dma_issue_pending(struct dma_chan *chan) | |||
597 | spin_unlock_irqrestore(&c->vc.lock, flags); | 600 | spin_unlock_irqrestore(&c->vc.lock, flags); |
598 | } | 601 | } |
599 | 602 | ||
603 | struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_memcpy( | ||
604 | struct dma_chan *chan, dma_addr_t dst, dma_addr_t src, | ||
605 | size_t len, unsigned long flags) | ||
606 | { | ||
607 | struct bcm2835_chan *c = to_bcm2835_dma_chan(chan); | ||
608 | struct bcm2835_desc *d; | ||
609 | u32 info = BCM2835_DMA_D_INC | BCM2835_DMA_S_INC; | ||
610 | u32 extra = BCM2835_DMA_INT_EN | BCM2835_DMA_WAIT_RESP; | ||
611 | size_t max_len = bcm2835_dma_max_frame_length(c); | ||
612 | size_t frames; | ||
613 | |||
614 | /* if src, dst or len is not given return with an error */ | ||
615 | if (!src || !dst || !len) | ||
616 | return NULL; | ||
617 | |||
618 | /* calculate number of frames */ | ||
619 | frames = bcm2835_dma_frames_for_length(len, max_len); | ||
620 | |||
621 | /* allocate the CB chain - this also fills in the pointers */ | ||
622 | d = bcm2835_dma_create_cb_chain(chan, DMA_MEM_TO_MEM, false, | ||
623 | info, extra, frames, | ||
624 | src, dst, len, 0, GFP_KERNEL); | ||
625 | if (!d) | ||
626 | return NULL; | ||
627 | |||
628 | return vchan_tx_prep(&c->vc, &d->vd, flags); | ||
629 | } | ||
630 | |||
600 | static struct dma_async_tx_descriptor *bcm2835_dma_prep_slave_sg( | 631 | static struct dma_async_tx_descriptor *bcm2835_dma_prep_slave_sg( |
601 | struct dma_chan *chan, | 632 | struct dma_chan *chan, |
602 | struct scatterlist *sgl, unsigned int sg_len, | 633 | struct scatterlist *sgl, unsigned int sg_len, |
@@ -880,17 +911,20 @@ static int bcm2835_dma_probe(struct platform_device *pdev) | |||
880 | dma_cap_set(DMA_PRIVATE, od->ddev.cap_mask); | 911 | dma_cap_set(DMA_PRIVATE, od->ddev.cap_mask); |
881 | dma_cap_set(DMA_CYCLIC, od->ddev.cap_mask); | 912 | dma_cap_set(DMA_CYCLIC, od->ddev.cap_mask); |
882 | dma_cap_set(DMA_SLAVE, od->ddev.cap_mask); | 913 | dma_cap_set(DMA_SLAVE, od->ddev.cap_mask); |
914 | dma_cap_set(DMA_MEMCPY, od->ddev.cap_mask); | ||
883 | od->ddev.device_alloc_chan_resources = bcm2835_dma_alloc_chan_resources; | 915 | od->ddev.device_alloc_chan_resources = bcm2835_dma_alloc_chan_resources; |
884 | od->ddev.device_free_chan_resources = bcm2835_dma_free_chan_resources; | 916 | od->ddev.device_free_chan_resources = bcm2835_dma_free_chan_resources; |
885 | od->ddev.device_tx_status = bcm2835_dma_tx_status; | 917 | od->ddev.device_tx_status = bcm2835_dma_tx_status; |
886 | od->ddev.device_issue_pending = bcm2835_dma_issue_pending; | 918 | od->ddev.device_issue_pending = bcm2835_dma_issue_pending; |
887 | od->ddev.device_prep_dma_cyclic = bcm2835_dma_prep_dma_cyclic; | 919 | od->ddev.device_prep_dma_cyclic = bcm2835_dma_prep_dma_cyclic; |
888 | od->ddev.device_prep_slave_sg = bcm2835_dma_prep_slave_sg; | 920 | od->ddev.device_prep_slave_sg = bcm2835_dma_prep_slave_sg; |
921 | od->ddev.device_prep_dma_memcpy = bcm2835_dma_prep_dma_memcpy; | ||
889 | od->ddev.device_config = bcm2835_dma_slave_config; | 922 | od->ddev.device_config = bcm2835_dma_slave_config; |
890 | od->ddev.device_terminate_all = bcm2835_dma_terminate_all; | 923 | od->ddev.device_terminate_all = bcm2835_dma_terminate_all; |
891 | od->ddev.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); | 924 | od->ddev.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); |
892 | od->ddev.dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); | 925 | od->ddev.dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); |
893 | od->ddev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); | 926 | od->ddev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV) | |
927 | BIT(DMA_MEM_TO_MEM); | ||
894 | od->ddev.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; | 928 | od->ddev.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; |
895 | od->ddev.dev = &pdev->dev; | 929 | od->ddev.dev = &pdev->dev; |
896 | INIT_LIST_HEAD(&od->ddev.channels); | 930 | INIT_LIST_HEAD(&od->ddev.channels); |