diff options
Diffstat (limited to 'drivers/dma')
| -rw-r--r-- | drivers/dma/Kconfig | 1 | ||||
| -rw-r--r-- | drivers/dma/at_hdmac.c | 9 | ||||
| -rw-r--r-- | drivers/dma/dw_dmac.c | 23 | ||||
| -rw-r--r-- | drivers/dma/dw_dmac_regs.h | 1 | ||||
| -rw-r--r-- | drivers/dma/omap-dma.c | 20 | ||||
| -rw-r--r-- | drivers/dma/pl330.c | 38 | 
6 files changed, 66 insertions, 26 deletions
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 80b69971cf2..aeaea32bcfd 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -83,6 +83,7 @@ config INTEL_IOP_ADMA  config DW_DMAC  	tristate "Synopsys DesignWare AHB DMA support" +	depends on GENERIC_HARDIRQS  	select DMA_ENGINE  	default y if CPU_AT32AP7000  	help diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index 6e13f262139..88cfc61329d 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -310,8 +310,6 @@ static void atc_complete_all(struct at_dma_chan *atchan)  	dev_vdbg(chan2dev(&atchan->chan_common), "complete all\n"); -	BUG_ON(atc_chan_is_enabled(atchan)); -  	/*  	 * Submit queued descriptors ASAP, i.e. before we go through  	 * the completed ones. @@ -368,6 +366,9 @@ static void atc_advance_work(struct at_dma_chan *atchan)  {  	dev_vdbg(chan2dev(&atchan->chan_common), "advance_work\n"); +	if (atc_chan_is_enabled(atchan)) +		return; +  	if (list_empty(&atchan->active_list) ||  	    list_is_singular(&atchan->active_list)) {  		atc_complete_all(atchan); @@ -1078,9 +1079,7 @@ static void atc_issue_pending(struct dma_chan *chan)  		return;  	spin_lock_irqsave(&atchan->lock, flags); -	if (!atc_chan_is_enabled(atchan)) { -		atc_advance_work(atchan); -	} +	atc_advance_work(atchan);  	spin_unlock_irqrestore(&atchan->lock, flags);  } diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c index c599558faed..43a5329d448 100644 --- a/drivers/dma/dw_dmac.c +++ b/drivers/dma/dw_dmac.c @@ -1001,6 +1001,13 @@ static inline void convert_burst(u32 *maxburst)  		*maxburst = 0;  } +static inline void convert_slave_id(struct dw_dma_chan *dwc) +{ +	struct dw_dma *dw = to_dw_dma(dwc->chan.device); + +	dwc->dma_sconfig.slave_id -= dw->request_line_base; +} +  static int  set_runtime_config(struct dma_chan *chan, struct dma_slave_config *sconfig)  { @@ -1015,6 +1022,7 @@ set_runtime_config(struct dma_chan *chan, struct dma_slave_config *sconfig)  	convert_burst(&dwc->dma_sconfig.src_maxburst);  	convert_burst(&dwc->dma_sconfig.dst_maxburst); +	convert_slave_id(dwc);  	return 0;  } @@ -1276,9 +1284,9 @@ static struct dma_chan *dw_dma_xlate(struct of_phandle_args *dma_spec,  	if (dma_spec->args_count != 3)  		return NULL; -	fargs.req = be32_to_cpup(dma_spec->args+0); -	fargs.src = be32_to_cpup(dma_spec->args+1); -	fargs.dst = be32_to_cpup(dma_spec->args+2); +	fargs.req = dma_spec->args[0]; +	fargs.src = dma_spec->args[1]; +	fargs.dst = dma_spec->args[2];  	if (WARN_ON(fargs.req >= DW_DMA_MAX_NR_REQUESTS ||  		    fargs.src >= dw->nr_masters || @@ -1628,6 +1636,7 @@ dw_dma_parse_dt(struct platform_device *pdev)  static int dw_probe(struct platform_device *pdev)  { +	const struct platform_device_id *match;  	struct dw_dma_platform_data *pdata;  	struct resource		*io;  	struct dw_dma		*dw; @@ -1711,6 +1720,11 @@ static int dw_probe(struct platform_device *pdev)  		memcpy(dw->data_width, pdata->data_width, 4);  	} +	/* Get the base request line if set */ +	match = platform_get_device_id(pdev); +	if (match) +		dw->request_line_base = (unsigned int)match->driver_data; +  	/* Calculate all channel mask before DMA setup */  	dw->all_chan_mask = (1 << nr_channels) - 1; @@ -1906,7 +1920,8 @@ MODULE_DEVICE_TABLE(of, dw_dma_id_table);  #endif  static const struct platform_device_id dw_dma_ids[] = { -	{ "INTL9C60", 0 }, +	/* Name,	Request Line Base */ +	{ "INTL9C60",	(kernel_ulong_t)16 },  	{ }  }; diff --git a/drivers/dma/dw_dmac_regs.h b/drivers/dma/dw_dmac_regs.h index cf0ce5c77d6..4d02c3669b7 100644 --- a/drivers/dma/dw_dmac_regs.h +++ b/drivers/dma/dw_dmac_regs.h @@ -247,6 +247,7 @@ struct dw_dma {  	/* hardware configuration */  	unsigned char		nr_masters;  	unsigned char		data_width[4]; +	unsigned int		request_line_base;  	struct dw_dma_chan	chan[0];  }; diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index c4b4fd2acc4..08b43bf3715 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c @@ -276,12 +276,20 @@ static void omap_dma_issue_pending(struct dma_chan *chan)  	spin_lock_irqsave(&c->vc.lock, flags);  	if (vchan_issue_pending(&c->vc) && !c->desc) { -		struct omap_dmadev *d = to_omap_dma_dev(chan->device); -		spin_lock(&d->lock); -		if (list_empty(&c->node)) -			list_add_tail(&c->node, &d->pending); -		spin_unlock(&d->lock); -		tasklet_schedule(&d->task); +		/* +		 * c->cyclic is used only by audio and in this case the DMA need +		 * to be started without delay. +		 */ +		if (!c->cyclic) { +			struct omap_dmadev *d = to_omap_dma_dev(chan->device); +			spin_lock(&d->lock); +			if (list_empty(&c->node)) +				list_add_tail(&c->node, &d->pending); +			spin_unlock(&d->lock); +			tasklet_schedule(&d->task); +		} else { +			omap_dma_start_desc(c); +		}  	}  	spin_unlock_irqrestore(&c->vc.lock, flags);  } diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c index 71815312275..5dbc5946c4c 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -2882,7 +2882,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)  {  	struct dma_pl330_platdata *pdat;  	struct dma_pl330_dmac *pdmac; -	struct dma_pl330_chan *pch; +	struct dma_pl330_chan *pch, *_p;  	struct pl330_info *pi;  	struct dma_device *pd;  	struct resource *res; @@ -2984,7 +2984,16 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)  	ret = dma_async_device_register(pd);  	if (ret) {  		dev_err(&adev->dev, "unable to register DMAC\n"); -		goto probe_err2; +		goto probe_err3; +	} + +	if (adev->dev.of_node) { +		ret = of_dma_controller_register(adev->dev.of_node, +					 of_dma_pl330_xlate, pdmac); +		if (ret) { +			dev_err(&adev->dev, +			"unable to register DMA to the generic DT DMA helpers\n"); +		}  	}  	dev_info(&adev->dev, @@ -2995,16 +3004,21 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)  		pi->pcfg.data_bus_width / 8, pi->pcfg.num_chan,  		pi->pcfg.num_peri, pi->pcfg.num_events); -	ret = of_dma_controller_register(adev->dev.of_node, -					 of_dma_pl330_xlate, pdmac); -	if (ret) { -		dev_err(&adev->dev, -		"unable to register DMA to the generic DT DMA helpers\n"); -		goto probe_err2; -	} -  	return 0; +probe_err3: +	amba_set_drvdata(adev, NULL); +	/* Idle the DMAC */ +	list_for_each_entry_safe(pch, _p, &pdmac->ddma.channels, +			chan.device_node) { + +		/* Remove the channel */ +		list_del(&pch->chan.device_node); + +		/* Flush the channel */ +		pl330_control(&pch->chan, DMA_TERMINATE_ALL, 0); +		pl330_free_chan_resources(&pch->chan); +	}  probe_err2:  	pl330_del(pi);  probe_err1: @@ -3023,8 +3037,10 @@ static int pl330_remove(struct amba_device *adev)  	if (!pdmac)  		return 0; -	of_dma_controller_free(adev->dev.of_node); +	if (adev->dev.of_node) +		of_dma_controller_free(adev->dev.of_node); +	dma_async_device_unregister(&pdmac->ddma);  	amba_set_drvdata(adev, NULL);  	/* Idle the DMAC */  |