aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma/s3c24xx-dma.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/dma/s3c24xx-dma.c')
-rw-r--r--drivers/dma/s3c24xx-dma.c75
1 files changed, 36 insertions, 39 deletions
diff --git a/drivers/dma/s3c24xx-dma.c b/drivers/dma/s3c24xx-dma.c
index 6941a77521c3..4d5a84815ba7 100644
--- a/drivers/dma/s3c24xx-dma.c
+++ b/drivers/dma/s3c24xx-dma.c
@@ -384,20 +384,30 @@ static u32 s3c24xx_dma_getbytes_chan(struct s3c24xx_dma_chan *s3cchan)
384 return tc * txd->width; 384 return tc * txd->width;
385} 385}
386 386
387static int s3c24xx_dma_set_runtime_config(struct s3c24xx_dma_chan *s3cchan, 387static int s3c24xx_dma_set_runtime_config(struct dma_chan *chan,
388 struct dma_slave_config *config) 388 struct dma_slave_config *config)
389{ 389{
390 if (!s3cchan->slave) 390 struct s3c24xx_dma_chan *s3cchan = to_s3c24xx_dma_chan(chan);
391 return -EINVAL; 391 unsigned long flags;
392 int ret = 0;
392 393
393 /* Reject definitely invalid configurations */ 394 /* Reject definitely invalid configurations */
394 if (config->src_addr_width == DMA_SLAVE_BUSWIDTH_8_BYTES || 395 if (config->src_addr_width == DMA_SLAVE_BUSWIDTH_8_BYTES ||
395 config->dst_addr_width == DMA_SLAVE_BUSWIDTH_8_BYTES) 396 config->dst_addr_width == DMA_SLAVE_BUSWIDTH_8_BYTES)
396 return -EINVAL; 397 return -EINVAL;
397 398
399 spin_lock_irqsave(&s3cchan->vc.lock, flags);
400
401 if (!s3cchan->slave) {
402 ret = -EINVAL;
403 goto out;
404 }
405
398 s3cchan->cfg = *config; 406 s3cchan->cfg = *config;
399 407
400 return 0; 408out:
409 spin_unlock_irqrestore(&s3cchan->vc.lock, flags);
410 return ret;
401} 411}
402 412
403/* 413/*
@@ -703,53 +713,38 @@ static irqreturn_t s3c24xx_dma_irq(int irq, void *data)
703 * The DMA ENGINE API 713 * The DMA ENGINE API
704 */ 714 */
705 715
706static int s3c24xx_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, 716static int s3c24xx_dma_terminate_all(struct dma_chan *chan)
707 unsigned long arg)
708{ 717{
709 struct s3c24xx_dma_chan *s3cchan = to_s3c24xx_dma_chan(chan); 718 struct s3c24xx_dma_chan *s3cchan = to_s3c24xx_dma_chan(chan);
710 struct s3c24xx_dma_engine *s3cdma = s3cchan->host; 719 struct s3c24xx_dma_engine *s3cdma = s3cchan->host;
711 unsigned long flags; 720 unsigned long flags;
712 int ret = 0;
713 721
714 spin_lock_irqsave(&s3cchan->vc.lock, flags); 722 spin_lock_irqsave(&s3cchan->vc.lock, flags);
715 723
716 switch (cmd) { 724 if (!s3cchan->phy && !s3cchan->at) {
717 case DMA_SLAVE_CONFIG: 725 dev_err(&s3cdma->pdev->dev, "trying to terminate already stopped channel %d\n",
718 ret = s3c24xx_dma_set_runtime_config(s3cchan, 726 s3cchan->id);
719 (struct dma_slave_config *)arg); 727 return -EINVAL;
720 break; 728 }
721 case DMA_TERMINATE_ALL:
722 if (!s3cchan->phy && !s3cchan->at) {
723 dev_err(&s3cdma->pdev->dev, "trying to terminate already stopped channel %d\n",
724 s3cchan->id);
725 ret = -EINVAL;
726 break;
727 }
728
729 s3cchan->state = S3C24XX_DMA_CHAN_IDLE;
730 729
731 /* Mark physical channel as free */ 730 s3cchan->state = S3C24XX_DMA_CHAN_IDLE;
732 if (s3cchan->phy)
733 s3c24xx_dma_phy_free(s3cchan);
734 731
735 /* Dequeue current job */ 732 /* Mark physical channel as free */
736 if (s3cchan->at) { 733 if (s3cchan->phy)
737 s3c24xx_dma_desc_free(&s3cchan->at->vd); 734 s3c24xx_dma_phy_free(s3cchan);
738 s3cchan->at = NULL;
739 }
740 735
741 /* Dequeue jobs not yet fired as well */ 736 /* Dequeue current job */
742 s3c24xx_dma_free_txd_list(s3cdma, s3cchan); 737 if (s3cchan->at) {
743 break; 738 s3c24xx_dma_desc_free(&s3cchan->at->vd);
744 default: 739 s3cchan->at = NULL;
745 /* Unknown command */
746 ret = -ENXIO;
747 break;
748 } 740 }
749 741
742 /* Dequeue jobs not yet fired as well */
743 s3c24xx_dma_free_txd_list(s3cdma, s3cchan);
744
750 spin_unlock_irqrestore(&s3cchan->vc.lock, flags); 745 spin_unlock_irqrestore(&s3cchan->vc.lock, flags);
751 746
752 return ret; 747 return 0;
753} 748}
754 749
755static int s3c24xx_dma_alloc_chan_resources(struct dma_chan *chan) 750static int s3c24xx_dma_alloc_chan_resources(struct dma_chan *chan)
@@ -1300,7 +1295,8 @@ static int s3c24xx_dma_probe(struct platform_device *pdev)
1300 s3cdma->memcpy.device_prep_dma_memcpy = s3c24xx_dma_prep_memcpy; 1295 s3cdma->memcpy.device_prep_dma_memcpy = s3c24xx_dma_prep_memcpy;
1301 s3cdma->memcpy.device_tx_status = s3c24xx_dma_tx_status; 1296 s3cdma->memcpy.device_tx_status = s3c24xx_dma_tx_status;
1302 s3cdma->memcpy.device_issue_pending = s3c24xx_dma_issue_pending; 1297 s3cdma->memcpy.device_issue_pending = s3c24xx_dma_issue_pending;
1303 s3cdma->memcpy.device_control = s3c24xx_dma_control; 1298 s3cdma->memcpy.device_config = s3c24xx_dma_set_runtime_config;
1299 s3cdma->memcpy.device_terminate_all = s3c24xx_dma_terminate_all;
1304 1300
1305 /* Initialize slave engine for SoC internal dedicated peripherals */ 1301 /* Initialize slave engine for SoC internal dedicated peripherals */
1306 dma_cap_set(DMA_SLAVE, s3cdma->slave.cap_mask); 1302 dma_cap_set(DMA_SLAVE, s3cdma->slave.cap_mask);
@@ -1315,7 +1311,8 @@ static int s3c24xx_dma_probe(struct platform_device *pdev)
1315 s3cdma->slave.device_issue_pending = s3c24xx_dma_issue_pending; 1311 s3cdma->slave.device_issue_pending = s3c24xx_dma_issue_pending;
1316 s3cdma->slave.device_prep_slave_sg = s3c24xx_dma_prep_slave_sg; 1312 s3cdma->slave.device_prep_slave_sg = s3c24xx_dma_prep_slave_sg;
1317 s3cdma->slave.device_prep_dma_cyclic = s3c24xx_dma_prep_dma_cyclic; 1313 s3cdma->slave.device_prep_dma_cyclic = s3c24xx_dma_prep_dma_cyclic;
1318 s3cdma->slave.device_control = s3c24xx_dma_control; 1314 s3cdma->slave.device_config = s3c24xx_dma_set_runtime_config;
1315 s3cdma->slave.device_terminate_all = s3c24xx_dma_terminate_all;
1319 1316
1320 /* Register as many memcpy channels as there are physical channels */ 1317 /* Register as many memcpy channels as there are physical channels */
1321 ret = s3c24xx_dma_init_virtual_channels(s3cdma, &s3cdma->memcpy, 1318 ret = s3c24xx_dma_init_virtual_channels(s3cdma, &s3cdma->memcpy,