summaryrefslogtreecommitdiffstats
path: root/drivers/dma
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/dma')
-rw-r--r--drivers/dma/Kconfig11
-rw-r--r--drivers/dma/dw_dmac_regs.h18
-rw-r--r--drivers/dma/imx-dma.c141
-rw-r--r--drivers/dma/imx-sdma.c1
-rw-r--r--drivers/dma/ipu/ipu_idmac.c3
-rw-r--r--drivers/dma/ipu/ipu_irq.c3
-rw-r--r--drivers/dma/sirf-dma.c4
7 files changed, 111 insertions, 70 deletions
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 677cd6e4e1a1..d4c12180c654 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -90,6 +90,17 @@ config DW_DMAC
Support the Synopsys DesignWare AHB DMA controller. This
can be integrated in chips such as the Atmel AT32ap7000.
+config DW_DMAC_BIG_ENDIAN_IO
+ bool "Use big endian I/O register access"
+ default y if AVR32
+ depends on DW_DMAC
+ help
+ Say yes here to use big endian I/O access when reading and writing
+ to the DMA controller registers. This is needed on some platforms,
+ like the Atmel AVR32 architecture.
+
+ If unsure, use the default setting.
+
config AT_HDMAC
tristate "Atmel AHB DMA support"
depends on ARCH_AT91
diff --git a/drivers/dma/dw_dmac_regs.h b/drivers/dma/dw_dmac_regs.h
index ff39fa6cd2bc..88965597b7d0 100644
--- a/drivers/dma/dw_dmac_regs.h
+++ b/drivers/dma/dw_dmac_regs.h
@@ -98,9 +98,17 @@ struct dw_dma_regs {
u32 DW_PARAMS;
};
+#ifdef CONFIG_DW_DMAC_BIG_ENDIAN_IO
+#define dma_readl_native ioread32be
+#define dma_writel_native iowrite32be
+#else
+#define dma_readl_native readl
+#define dma_writel_native writel
+#endif
+
/* To access the registers in early stage of probe */
#define dma_read_byaddr(addr, name) \
- readl((addr) + offsetof(struct dw_dma_regs, name))
+ dma_readl_native((addr) + offsetof(struct dw_dma_regs, name))
/* Bitfields in DW_PARAMS */
#define DW_PARAMS_NR_CHAN 8 /* number of channels */
@@ -216,9 +224,9 @@ __dwc_regs(struct dw_dma_chan *dwc)
}
#define channel_readl(dwc, name) \
- readl(&(__dwc_regs(dwc)->name))
+ dma_readl_native(&(__dwc_regs(dwc)->name))
#define channel_writel(dwc, name, val) \
- writel((val), &(__dwc_regs(dwc)->name))
+ dma_writel_native((val), &(__dwc_regs(dwc)->name))
static inline struct dw_dma_chan *to_dw_dma_chan(struct dma_chan *chan)
{
@@ -246,9 +254,9 @@ static inline struct dw_dma_regs __iomem *__dw_regs(struct dw_dma *dw)
}
#define dma_readl(dw, name) \
- readl(&(__dw_regs(dw)->name))
+ dma_readl_native(&(__dw_regs(dw)->name))
#define dma_writel(dw, name, val) \
- writel((val), &(__dw_regs(dw)->name))
+ dma_writel_native((val), &(__dw_regs(dw)->name))
#define channel_set_bit(dw, reg, mask) \
dma_writel(dw, reg, ((mask) << 8) | (mask))
diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c
index f11b5b2b1a1c..dbf0e6f8de8a 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,8 +182,40 @@ 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)
{
return container_of(chan, struct imxdma_channel, 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);
@@ -474,8 +513,10 @@ static int imxdma_xfer_desc(struct imxdma_desc *d)
slot = i;
break;
}
- if (slot < 0)
+ if (slot < 0) {
+ spin_unlock_irqrestore(&imxdma->lock, flags);
return -EBUSY;
+ }
imxdma->slots_2d[slot].xsr = d->x;
imxdma->slots_2d[slot].ysr = d->y;
@@ -959,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);
@@ -995,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;
}
}
@@ -1036,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;
@@ -1089,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;
}
@@ -1137,6 +1161,7 @@ static struct platform_driver imxdma_driver = {
.driver = {
.name = "imx-dma",
},
+ .id_table = imx_dma_devtype,
.remove = __exit_p(imxdma_remove),
};
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index c099ca0846f4..f082aa3a918c 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -40,7 +40,6 @@
#include <asm/irq.h>
#include <linux/platform_data/dma-imx-sdma.h>
#include <linux/platform_data/dma-imx.h>
-#include <mach/hardware.h>
#include "dmaengine.h"
diff --git a/drivers/dma/ipu/ipu_idmac.c b/drivers/dma/ipu/ipu_idmac.c
index c7573e50aa14..65855373cee6 100644
--- a/drivers/dma/ipu/ipu_idmac.c
+++ b/drivers/dma/ipu/ipu_idmac.c
@@ -22,8 +22,7 @@
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/module.h>
-
-#include <mach/ipu.h>
+#include <linux/dma/ipu-dma.h>
#include "../dmaengine.h"
#include "ipu_intern.h"
diff --git a/drivers/dma/ipu/ipu_irq.c b/drivers/dma/ipu/ipu_irq.c
index fa95bcc3de1f..a5ee37d5320f 100644
--- a/drivers/dma/ipu/ipu_irq.c
+++ b/drivers/dma/ipu/ipu_irq.c
@@ -15,8 +15,7 @@
#include <linux/irq.h>
#include <linux/io.h>
#include <linux/module.h>
-
-#include <mach/ipu.h>
+#include <linux/dma/ipu-dma.h>
#include "ipu_intern.h"
diff --git a/drivers/dma/sirf-dma.c b/drivers/dma/sirf-dma.c
index 64385cde044b..d451caace806 100644
--- a/drivers/dma/sirf-dma.c
+++ b/drivers/dma/sirf-dma.c
@@ -109,7 +109,7 @@ static void sirfsoc_dma_execute(struct sirfsoc_dma_chan *schan)
sdesc = list_first_entry(&schan->queued, struct sirfsoc_dma_desc,
node);
/* Move the first queued descriptor to active list */
- list_move_tail(&schan->queued, &schan->active);
+ list_move_tail(&sdesc->node, &schan->active);
/* Start the DMA transfer */
writel_relaxed(sdesc->width, sdma->base + SIRFSOC_DMA_WIDTH_0 +
@@ -428,7 +428,7 @@ static struct dma_async_tx_descriptor *sirfsoc_dma_prep_interleaved(
unsigned long iflags;
int ret;
- if ((xt->dir != DMA_MEM_TO_DEV) || (xt->dir != DMA_DEV_TO_MEM)) {
+ if ((xt->dir != DMA_MEM_TO_DEV) && (xt->dir != DMA_DEV_TO_MEM)) {
ret = -EINVAL;
goto err_dir;
}