Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

dmaengine: omap-dma: Add support for memcpy

The sDMA controller is capable of performing memory copy operation. It need
to be configured to software triggered mode and without HW synchronization.
The sDMA can copy data which is aligned to 8, 16 or 32 bits.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>

authored by

Peter Ujfalusi and committed by
Vinod Koul
4ce98c0a 5ebe6afa

+49 -2
+49 -2
drivers/dma/omap-dma.c
··· 362 362 struct omap_sg *sg = d->sg + idx; 363 363 unsigned cxsa, cxei, cxfi; 364 364 365 - if (d->dir == DMA_DEV_TO_MEM) { 365 + if (d->dir == DMA_DEV_TO_MEM || d->dir == DMA_MEM_TO_MEM) { 366 366 cxsa = CDSA; 367 367 cxei = CDEI; 368 368 cxfi = CDFI; ··· 408 408 if (dma_omap1()) 409 409 omap_dma_chan_write(c, CCR2, d->ccr >> 16); 410 410 411 - if (d->dir == DMA_DEV_TO_MEM) { 411 + if (d->dir == DMA_DEV_TO_MEM || d->dir == DMA_MEM_TO_MEM) { 412 412 cxsa = CSSA; 413 413 cxei = CSEI; 414 414 cxfi = CSFI; ··· 948 948 return vchan_tx_prep(&c->vc, &d->vd, flags); 949 949 } 950 950 951 + static struct dma_async_tx_descriptor *omap_dma_prep_dma_memcpy( 952 + struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, 953 + size_t len, unsigned long tx_flags) 954 + { 955 + struct omap_chan *c = to_omap_dma_chan(chan); 956 + struct omap_desc *d; 957 + uint8_t data_type; 958 + 959 + d = kzalloc(sizeof(*d) + sizeof(d->sg[0]), GFP_ATOMIC); 960 + if (!d) 961 + return NULL; 962 + 963 + data_type = __ffs((src | dest | len)); 964 + if (data_type > CSDP_DATA_TYPE_32) 965 + data_type = CSDP_DATA_TYPE_32; 966 + 967 + d->dir = DMA_MEM_TO_MEM; 968 + d->dev_addr = src; 969 + d->fi = 0; 970 + d->es = data_type; 971 + d->sg[0].en = len / BIT(data_type); 972 + d->sg[0].fn = 1; 973 + d->sg[0].addr = dest; 974 + d->sglen = 1; 975 + d->ccr = c->ccr; 976 + d->ccr |= CCR_DST_AMODE_POSTINC | CCR_SRC_AMODE_POSTINC; 977 + 978 + d->cicr = CICR_DROP_IE; 979 + if (tx_flags & DMA_PREP_INTERRUPT) 980 + d->cicr |= CICR_FRAME_IE; 981 + 982 + d->csdp = data_type; 983 + 984 + if (dma_omap1()) { 985 + d->cicr |= CICR_TOUT_IE; 986 + d->csdp |= CSDP_DST_PORT_EMIFF | CSDP_SRC_PORT_EMIFF; 987 + } else { 988 + d->csdp |= CSDP_DST_PACKED | CSDP_SRC_PACKED; 989 + d->cicr |= CICR_MISALIGNED_ERR_IE | CICR_TRANS_ERR_IE; 990 + d->csdp |= CSDP_DST_BURST_64 | CSDP_SRC_BURST_64; 991 + } 992 + 993 + return vchan_tx_prep(&c->vc, &d->vd, tx_flags); 994 + } 995 + 951 996 static int omap_dma_slave_config(struct dma_chan *chan, struct dma_slave_config *cfg) 952 997 { 953 998 struct omap_chan *c = to_omap_dma_chan(chan); ··· 1139 1094 1140 1095 dma_cap_set(DMA_SLAVE, od->ddev.cap_mask); 1141 1096 dma_cap_set(DMA_CYCLIC, od->ddev.cap_mask); 1097 + dma_cap_set(DMA_MEMCPY, od->ddev.cap_mask); 1142 1098 od->ddev.device_alloc_chan_resources = omap_dma_alloc_chan_resources; 1143 1099 od->ddev.device_free_chan_resources = omap_dma_free_chan_resources; 1144 1100 od->ddev.device_tx_status = omap_dma_tx_status; 1145 1101 od->ddev.device_issue_pending = omap_dma_issue_pending; 1146 1102 od->ddev.device_prep_slave_sg = omap_dma_prep_slave_sg; 1147 1103 od->ddev.device_prep_dma_cyclic = omap_dma_prep_dma_cyclic; 1104 + od->ddev.device_prep_dma_memcpy = omap_dma_prep_dma_memcpy; 1148 1105 od->ddev.device_config = omap_dma_slave_config; 1149 1106 od->ddev.device_pause = omap_dma_pause; 1150 1107 od->ddev.device_resume = omap_dma_resume;