aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/dma/fsl-edma-common.c66
-rw-r--r--drivers/dma/fsl-edma-common.h4
-rw-r--r--drivers/dma/fsl-edma.c1
-rw-r--r--drivers/dma/mcf-edma.c1
4 files changed, 68 insertions, 4 deletions
diff --git a/drivers/dma/fsl-edma-common.c b/drivers/dma/fsl-edma-common.c
index fe529100674f..680b2a00a953 100644
--- a/drivers/dma/fsl-edma-common.c
+++ b/drivers/dma/fsl-edma-common.c
@@ -6,6 +6,7 @@
6#include <linux/dmapool.h> 6#include <linux/dmapool.h>
7#include <linux/module.h> 7#include <linux/module.h>
8#include <linux/slab.h> 8#include <linux/slab.h>
9#include <linux/dma-mapping.h>
9 10
10#include "fsl-edma-common.h" 11#include "fsl-edma-common.h"
11 12
@@ -173,12 +174,62 @@ int fsl_edma_resume(struct dma_chan *chan)
173} 174}
174EXPORT_SYMBOL_GPL(fsl_edma_resume); 175EXPORT_SYMBOL_GPL(fsl_edma_resume);
175 176
177static void fsl_edma_unprep_slave_dma(struct fsl_edma_chan *fsl_chan)
178{
179 if (fsl_chan->dma_dir != DMA_NONE)
180 dma_unmap_resource(fsl_chan->vchan.chan.device->dev,
181 fsl_chan->dma_dev_addr,
182 fsl_chan->dma_dev_size,
183 fsl_chan->dma_dir, 0);
184 fsl_chan->dma_dir = DMA_NONE;
185}
186
187static bool fsl_edma_prep_slave_dma(struct fsl_edma_chan *fsl_chan,
188 enum dma_transfer_direction dir)
189{
190 struct device *dev = fsl_chan->vchan.chan.device->dev;
191 enum dma_data_direction dma_dir;
192 phys_addr_t addr = 0;
193 u32 size = 0;
194
195 switch (dir) {
196 case DMA_MEM_TO_DEV:
197 dma_dir = DMA_FROM_DEVICE;
198 addr = fsl_chan->cfg.dst_addr;
199 size = fsl_chan->cfg.dst_maxburst;
200 break;
201 case DMA_DEV_TO_MEM:
202 dma_dir = DMA_TO_DEVICE;
203 addr = fsl_chan->cfg.src_addr;
204 size = fsl_chan->cfg.src_maxburst;
205 break;
206 default:
207 dma_dir = DMA_NONE;
208 break;
209 }
210
211 /* Already mapped for this config? */
212 if (fsl_chan->dma_dir == dma_dir)
213 return true;
214
215 fsl_edma_unprep_slave_dma(fsl_chan);
216
217 fsl_chan->dma_dev_addr = dma_map_resource(dev, addr, size, dma_dir, 0);
218 if (dma_mapping_error(dev, fsl_chan->dma_dev_addr))
219 return false;
220 fsl_chan->dma_dev_size = size;
221 fsl_chan->dma_dir = dma_dir;
222
223 return true;
224}
225
176int fsl_edma_slave_config(struct dma_chan *chan, 226int fsl_edma_slave_config(struct dma_chan *chan,
177 struct dma_slave_config *cfg) 227 struct dma_slave_config *cfg)
178{ 228{
179 struct fsl_edma_chan *fsl_chan = to_fsl_edma_chan(chan); 229 struct fsl_edma_chan *fsl_chan = to_fsl_edma_chan(chan);
180 230
181 memcpy(&fsl_chan->cfg, cfg, sizeof(*cfg)); 231 memcpy(&fsl_chan->cfg, cfg, sizeof(*cfg));
232 fsl_edma_unprep_slave_dma(fsl_chan);
182 233
183 return 0; 234 return 0;
184} 235}
@@ -376,6 +427,9 @@ struct dma_async_tx_descriptor *fsl_edma_prep_dma_cyclic(
376 if (!is_slave_direction(direction)) 427 if (!is_slave_direction(direction))
377 return NULL; 428 return NULL;
378 429
430 if (!fsl_edma_prep_slave_dma(fsl_chan, direction))
431 return NULL;
432
379 sg_len = buf_len / period_len; 433 sg_len = buf_len / period_len;
380 fsl_desc = fsl_edma_alloc_desc(fsl_chan, sg_len); 434 fsl_desc = fsl_edma_alloc_desc(fsl_chan, sg_len);
381 if (!fsl_desc) 435 if (!fsl_desc)
@@ -407,11 +461,11 @@ struct dma_async_tx_descriptor *fsl_edma_prep_dma_cyclic(
407 461
408 if (direction == DMA_MEM_TO_DEV) { 462 if (direction == DMA_MEM_TO_DEV) {
409 src_addr = dma_buf_next; 463 src_addr = dma_buf_next;
410 dst_addr = fsl_chan->cfg.dst_addr; 464 dst_addr = fsl_chan->dma_dev_addr;
411 soff = fsl_chan->cfg.dst_addr_width; 465 soff = fsl_chan->cfg.dst_addr_width;
412 doff = 0; 466 doff = 0;
413 } else { 467 } else {
414 src_addr = fsl_chan->cfg.src_addr; 468 src_addr = fsl_chan->dma_dev_addr;
415 dst_addr = dma_buf_next; 469 dst_addr = dma_buf_next;
416 soff = 0; 470 soff = 0;
417 doff = fsl_chan->cfg.src_addr_width; 471 doff = fsl_chan->cfg.src_addr_width;
@@ -442,6 +496,9 @@ struct dma_async_tx_descriptor *fsl_edma_prep_slave_sg(
442 if (!is_slave_direction(direction)) 496 if (!is_slave_direction(direction))
443 return NULL; 497 return NULL;
444 498
499 if (!fsl_edma_prep_slave_dma(fsl_chan, direction))
500 return NULL;
501
445 fsl_desc = fsl_edma_alloc_desc(fsl_chan, sg_len); 502 fsl_desc = fsl_edma_alloc_desc(fsl_chan, sg_len);
446 if (!fsl_desc) 503 if (!fsl_desc)
447 return NULL; 504 return NULL;
@@ -466,11 +523,11 @@ struct dma_async_tx_descriptor *fsl_edma_prep_slave_sg(
466 523
467 if (direction == DMA_MEM_TO_DEV) { 524 if (direction == DMA_MEM_TO_DEV) {
468 src_addr = sg_dma_address(sg); 525 src_addr = sg_dma_address(sg);
469 dst_addr = fsl_chan->cfg.dst_addr; 526 dst_addr = fsl_chan->dma_dev_addr;
470 soff = fsl_chan->cfg.dst_addr_width; 527 soff = fsl_chan->cfg.dst_addr_width;
471 doff = 0; 528 doff = 0;
472 } else { 529 } else {
473 src_addr = fsl_chan->cfg.src_addr; 530 src_addr = fsl_chan->dma_dev_addr;
474 dst_addr = sg_dma_address(sg); 531 dst_addr = sg_dma_address(sg);
475 soff = 0; 532 soff = 0;
476 doff = fsl_chan->cfg.src_addr_width; 533 doff = fsl_chan->cfg.src_addr_width;
@@ -553,6 +610,7 @@ void fsl_edma_free_chan_resources(struct dma_chan *chan)
553 fsl_edma_chan_mux(fsl_chan, 0, false); 610 fsl_edma_chan_mux(fsl_chan, 0, false);
554 fsl_chan->edesc = NULL; 611 fsl_chan->edesc = NULL;
555 vchan_get_all_descriptors(&fsl_chan->vchan, &head); 612 vchan_get_all_descriptors(&fsl_chan->vchan, &head);
613 fsl_edma_unprep_slave_dma(fsl_chan);
556 spin_unlock_irqrestore(&fsl_chan->vchan.lock, flags); 614 spin_unlock_irqrestore(&fsl_chan->vchan.lock, flags);
557 615
558 vchan_dma_desc_free_list(&fsl_chan->vchan, &head); 616 vchan_dma_desc_free_list(&fsl_chan->vchan, &head);
diff --git a/drivers/dma/fsl-edma-common.h b/drivers/dma/fsl-edma-common.h
index 8917e8865959..b435d8e1e3a1 100644
--- a/drivers/dma/fsl-edma-common.h
+++ b/drivers/dma/fsl-edma-common.h
@@ -6,6 +6,7 @@
6#ifndef _FSL_EDMA_COMMON_H_ 6#ifndef _FSL_EDMA_COMMON_H_
7#define _FSL_EDMA_COMMON_H_ 7#define _FSL_EDMA_COMMON_H_
8 8
9#include <linux/dma-direction.h>
9#include "virt-dma.h" 10#include "virt-dma.h"
10 11
11#define EDMA_CR_EDBG BIT(1) 12#define EDMA_CR_EDBG BIT(1)
@@ -120,6 +121,9 @@ struct fsl_edma_chan {
120 struct dma_slave_config cfg; 121 struct dma_slave_config cfg;
121 u32 attr; 122 u32 attr;
122 struct dma_pool *tcd_pool; 123 struct dma_pool *tcd_pool;
124 dma_addr_t dma_dev_addr;
125 u32 dma_dev_size;
126 enum dma_data_direction dma_dir;
123}; 127};
124 128
125struct fsl_edma_desc { 129struct fsl_edma_desc {
diff --git a/drivers/dma/fsl-edma.c b/drivers/dma/fsl-edma.c
index 34d70112fcc9..75e8a7ba3a22 100644
--- a/drivers/dma/fsl-edma.c
+++ b/drivers/dma/fsl-edma.c
@@ -254,6 +254,7 @@ static int fsl_edma_probe(struct platform_device *pdev)
254 fsl_chan->pm_state = RUNNING; 254 fsl_chan->pm_state = RUNNING;
255 fsl_chan->slave_id = 0; 255 fsl_chan->slave_id = 0;
256 fsl_chan->idle = true; 256 fsl_chan->idle = true;
257 fsl_chan->dma_dir = DMA_NONE;
257 fsl_chan->vchan.desc_free = fsl_edma_free_desc; 258 fsl_chan->vchan.desc_free = fsl_edma_free_desc;
258 vchan_init(&fsl_chan->vchan, &fsl_edma->dma_dev); 259 vchan_init(&fsl_chan->vchan, &fsl_edma->dma_dev);
259 260
diff --git a/drivers/dma/mcf-edma.c b/drivers/dma/mcf-edma.c
index 5de1b07eddff..7de54b2fafdb 100644
--- a/drivers/dma/mcf-edma.c
+++ b/drivers/dma/mcf-edma.c
@@ -214,6 +214,7 @@ static int mcf_edma_probe(struct platform_device *pdev)
214 mcf_chan->edma = mcf_edma; 214 mcf_chan->edma = mcf_edma;
215 mcf_chan->slave_id = i; 215 mcf_chan->slave_id = i;
216 mcf_chan->idle = true; 216 mcf_chan->idle = true;
217 mcf_chan->dma_dir = DMA_NONE;
217 mcf_chan->vchan.desc_free = fsl_edma_free_desc; 218 mcf_chan->vchan.desc_free = fsl_edma_free_desc;
218 vchan_init(&mcf_chan->vchan, &mcf_edma->dma_dev); 219 vchan_init(&mcf_chan->vchan, &mcf_edma->dma_dev);
219 iowrite32(0x0, &regs->tcd[i].csr); 220 iowrite32(0x0, &regs->tcd[i].csr);