diff options
| -rw-r--r-- | drivers/dma/fsl-edma-common.c | 66 | ||||
| -rw-r--r-- | drivers/dma/fsl-edma-common.h | 4 | ||||
| -rw-r--r-- | drivers/dma/fsl-edma.c | 1 | ||||
| -rw-r--r-- | drivers/dma/mcf-edma.c | 1 |
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 | } |
| 174 | EXPORT_SYMBOL_GPL(fsl_edma_resume); | 175 | EXPORT_SYMBOL_GPL(fsl_edma_resume); |
| 175 | 176 | ||
| 177 | static 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 | |||
| 187 | static 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 | |||
| 176 | int fsl_edma_slave_config(struct dma_chan *chan, | 226 | int 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 | ||
| 125 | struct fsl_edma_desc { | 129 | struct 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, ®s->tcd[i].csr); | 220 | iowrite32(0x0, ®s->tcd[i].csr); |
