diff options
Diffstat (limited to 'drivers/dma/imx-dma.c')
| -rw-r--r-- | drivers/dma/imx-dma.c | 137 | 
1 files changed, 80 insertions, 57 deletions
diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c index 7d9554cc497..dbf0e6f8de8 100644 --- a/drivers/dma/imx-dma.c +++ b/drivers/dma/imx-dma.c @@ -29,7 +29,6 @@  #include <asm/irq.h>  #include <linux/platform_data/dma-imx.h> -#include <mach/hardware.h>  #include "dmaengine.h"  #define IMXDMA_MAX_CHAN_DESCRIPTORS	16 @@ -167,6 +166,12 @@ struct imxdma_channel {  	int				slot_2d;  }; +enum imx_dma_type { +	IMX1_DMA, +	IMX21_DMA, +	IMX27_DMA, +}; +  struct imxdma_engine {  	struct device			*dev;  	struct device_dma_parameters	dma_parms; @@ -177,7 +182,39 @@ struct imxdma_engine {  	spinlock_t			lock;  	struct imx_dma_2d_config	slots_2d[IMX_DMA_2D_SLOTS];  	struct imxdma_channel		channel[IMX_DMA_CHANNELS]; +	enum imx_dma_type		devtype; +}; + +static struct platform_device_id imx_dma_devtype[] = { +	{ +		.name = "imx1-dma", +		.driver_data = IMX1_DMA, +	}, { +		.name = "imx21-dma", +		.driver_data = IMX21_DMA, +	}, { +		.name = "imx27-dma", +		.driver_data = IMX27_DMA, +	}, { +		/* sentinel */ +	}  }; +MODULE_DEVICE_TABLE(platform, imx_dma_devtype); + +static inline int is_imx1_dma(struct imxdma_engine *imxdma) +{ +	return imxdma->devtype == IMX1_DMA; +} + +static inline int is_imx21_dma(struct imxdma_engine *imxdma) +{ +	return imxdma->devtype == IMX21_DMA; +} + +static inline int is_imx27_dma(struct imxdma_engine *imxdma) +{ +	return imxdma->devtype == IMX27_DMA; +}  static struct imxdma_channel *to_imxdma_chan(struct dma_chan *chan)  { @@ -212,7 +249,9 @@ static unsigned imx_dmav1_readl(struct imxdma_engine *imxdma, unsigned offset)  static int imxdma_hw_chain(struct imxdma_channel *imxdmac)  { -	if (cpu_is_mx27()) +	struct imxdma_engine *imxdma = imxdmac->imxdma; + +	if (is_imx27_dma(imxdma))  		return imxdmac->hw_chaining;  	else  		return 0; @@ -267,7 +306,7 @@ static void imxdma_enable_hw(struct imxdma_desc *d)  	imx_dmav1_writel(imxdma, imx_dmav1_readl(imxdma, DMA_CCR(channel)) |  			 CCR_CEN | CCR_ACRPT, DMA_CCR(channel)); -	if ((cpu_is_mx21() || cpu_is_mx27()) && +	if (!is_imx1_dma(imxdma) &&  			d->sg && imxdma_hw_chain(imxdmac)) {  		d->sg = sg_next(d->sg);  		if (d->sg) { @@ -436,7 +475,7 @@ static irqreturn_t dma_irq_handler(int irq, void *dev_id)  	struct imxdma_engine *imxdma = dev_id;  	int i, disr; -	if (cpu_is_mx21() || cpu_is_mx27()) +	if (!is_imx1_dma(imxdma))  		imxdma_err_handler(irq, dev_id);  	disr = imx_dmav1_readl(imxdma, DMA_DISR); @@ -961,35 +1000,32 @@ static void imxdma_issue_pending(struct dma_chan *chan)  static int __init imxdma_probe(struct platform_device *pdev)  	{  	struct imxdma_engine *imxdma; +	struct resource *res;  	int ret, i; +	int irq, irq_err; - -	imxdma = kzalloc(sizeof(*imxdma), GFP_KERNEL); +	imxdma = devm_kzalloc(&pdev->dev, sizeof(*imxdma), GFP_KERNEL);  	if (!imxdma)  		return -ENOMEM; -	if (cpu_is_mx1()) { -		imxdma->base = MX1_IO_ADDRESS(MX1_DMA_BASE_ADDR); -	} else if (cpu_is_mx21()) { -		imxdma->base = MX21_IO_ADDRESS(MX21_DMA_BASE_ADDR); -	} else if (cpu_is_mx27()) { -		imxdma->base = MX27_IO_ADDRESS(MX27_DMA_BASE_ADDR); -	} else { -		kfree(imxdma); -		return 0; -	} +	imxdma->devtype = pdev->id_entry->driver_data; + +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +	imxdma->base = devm_request_and_ioremap(&pdev->dev, res); +	if (!imxdma->base) +		return -EADDRNOTAVAIL; + +	irq = platform_get_irq(pdev, 0); +	if (irq < 0) +		return irq;  	imxdma->dma_ipg = devm_clk_get(&pdev->dev, "ipg"); -	if (IS_ERR(imxdma->dma_ipg)) { -		ret = PTR_ERR(imxdma->dma_ipg); -		goto err_clk; -	} +	if (IS_ERR(imxdma->dma_ipg)) +		return PTR_ERR(imxdma->dma_ipg);  	imxdma->dma_ahb = devm_clk_get(&pdev->dev, "ahb"); -	if (IS_ERR(imxdma->dma_ahb)) { -		ret = PTR_ERR(imxdma->dma_ahb); -		goto err_clk; -	} +	if (IS_ERR(imxdma->dma_ahb)) +		return PTR_ERR(imxdma->dma_ahb);  	clk_prepare_enable(imxdma->dma_ipg);  	clk_prepare_enable(imxdma->dma_ahb); @@ -997,18 +1033,25 @@ static int __init imxdma_probe(struct platform_device *pdev)  	/* reset DMA module */  	imx_dmav1_writel(imxdma, DCR_DRST, DMA_DCR); -	if (cpu_is_mx1()) { -		ret = request_irq(MX1_DMA_INT, dma_irq_handler, 0, "DMA", imxdma); +	if (is_imx1_dma(imxdma)) { +		ret = devm_request_irq(&pdev->dev, irq, +				       dma_irq_handler, 0, "DMA", imxdma);  		if (ret) {  			dev_warn(imxdma->dev, "Can't register IRQ for DMA\n"); -			goto err_enable; +			goto err; +		} + +		irq_err = platform_get_irq(pdev, 1); +		if (irq_err < 0) { +			ret = irq_err; +			goto err;  		} -		ret = request_irq(MX1_DMA_ERR, imxdma_err_handler, 0, "DMA", imxdma); +		ret = devm_request_irq(&pdev->dev, irq_err, +				       imxdma_err_handler, 0, "DMA", imxdma);  		if (ret) {  			dev_warn(imxdma->dev, "Can't register ERRIRQ for DMA\n"); -			free_irq(MX1_DMA_INT, NULL); -			goto err_enable; +			goto err;  		}  	} @@ -1038,14 +1081,14 @@ static int __init imxdma_probe(struct platform_device *pdev)  	for (i = 0; i < IMX_DMA_CHANNELS; i++) {  		struct imxdma_channel *imxdmac = &imxdma->channel[i]; -		if (cpu_is_mx21() || cpu_is_mx27()) { -			ret = request_irq(MX2x_INT_DMACH0 + i, +		if (!is_imx1_dma(imxdma)) { +			ret = devm_request_irq(&pdev->dev, irq + i,  					dma_irq_handler, 0, "DMA", imxdma);  			if (ret) {  				dev_warn(imxdma->dev, "Can't register IRQ %d "  					 "for DMA channel %d\n", -					 MX2x_INT_DMACH0 + i, i); -				goto err_init; +					 irq + i, i); +				goto err;  			}  			init_timer(&imxdmac->watchdog);  			imxdmac->watchdog.function = &imxdma_watchdog; @@ -1091,46 +1134,25 @@ static int __init imxdma_probe(struct platform_device *pdev)  	ret = dma_async_device_register(&imxdma->dma_device);  	if (ret) {  		dev_err(&pdev->dev, "unable to register\n"); -		goto err_init; +		goto err;  	}  	return 0; -err_init: - -	if (cpu_is_mx21() || cpu_is_mx27()) { -		while (--i >= 0) -			free_irq(MX2x_INT_DMACH0 + i, NULL); -	} else if cpu_is_mx1() { -		free_irq(MX1_DMA_INT, NULL); -		free_irq(MX1_DMA_ERR, NULL); -	} -err_enable: +err:  	clk_disable_unprepare(imxdma->dma_ipg);  	clk_disable_unprepare(imxdma->dma_ahb); -err_clk: -	kfree(imxdma);  	return ret;  }  static int __exit imxdma_remove(struct platform_device *pdev)  {  	struct imxdma_engine *imxdma = platform_get_drvdata(pdev); -	int i;          dma_async_device_unregister(&imxdma->dma_device); -	if (cpu_is_mx21() || cpu_is_mx27()) { -		for (i = 0; i < IMX_DMA_CHANNELS; i++) -			free_irq(MX2x_INT_DMACH0 + i, NULL); -	} else if cpu_is_mx1() { -		free_irq(MX1_DMA_INT, NULL); -		free_irq(MX1_DMA_ERR, NULL); -	} -  	clk_disable_unprepare(imxdma->dma_ipg);  	clk_disable_unprepare(imxdma->dma_ahb); -	kfree(imxdma);          return 0;  } @@ -1139,6 +1161,7 @@ static struct platform_driver imxdma_driver = {  	.driver		= {  		.name	= "imx-dma",  	}, +	.id_table	= imx_dma_devtype,  	.remove		= __exit_p(imxdma_remove),  };  |