summaryrefslogtreecommitdiff
path: root/drivers/dma/imx-sdma.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-07-28 15:45:17 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2016-07-28 15:45:17 -0700
commit6039b80eb50a893476fea7d56e86ed2d19290054 (patch)
tree9cb535ca7604f4e1859dfac221ada671368b149b /drivers/dma/imx-sdma.c
parentc9b011a87dd49bac1632311811c974bb7cd33c25 (diff)
parent4bb0439626983fdde5af3ce970bd0ba2070f5378 (diff)
Merge tag 'dmaengine-4.8-rc1' of git://git.infradead.org/users/vkoul/slave-dma
Pull dmaengine updates from Vinod Koul: "This time we have bit of largish changes: two new drivers, bunch of updates and cleanups to existing set. Nothing super exciting though. New drivers: - Xilinx zynqmp dma engine driver - Marvell xor2 driver Updates: - dmatest sg support - updates and enhancements to Xilinx drivers, adding of cyclic mode - clock handling fixes across drivers - removal of OOM messages on kzalloc across subsystem - interleaved transfers support in omap driver - runtime pm support in qcom bam dma - tasklet kill freeup across drivers - irq cleanup on remove across drivers" * tag 'dmaengine-4.8-rc1' of git://git.infradead.org/users/vkoul/slave-dma: (94 commits) dmaengine: k3dma: add missing clk_disable_unprepare() on error in k3_dma_probe() dmaengine: zynqmp_dma: add missing MODULE_LICENSE dmaengine: qcom_hidma: use for_each_matching_node() macro dmaengine: zynqmp_dma: Fix static checker warning dmaengine: omap-dma: Support for interleaved transfer dmaengine: ioat: statify symbol dmaengine: pxa_dma: implement device_synchronize dmaengine: imx-sdma: remove assignment never used dmaengine: imx-sdma: remove dummy assignment dmaengine: cppi: remove unused and bogus check dmaengine: qcom_hidma_lli: kill the tasklets upon exit dmaengine: pxa_dma: remove owner assignment dmaengine: fsl_raid: remove owner assignment dmaengine: coh901318: remove owner assignment dmaengine: qcom_hidma: kill the tasklets upon exit dmaengine: txx9dmac: explicitly freeup irq dmaengine: sirf-dma: kill the tasklets upon exit dmaengine: s3c24xx: kill the tasklets upon exit dmaengine: s3c24xx: explicitly freeup irq dmaengine: pl330: explicitly freeup irq ...
Diffstat (limited to 'drivers/dma/imx-sdma.c')
-rw-r--r--drivers/dma/imx-sdma.c32
1 files changed, 13 insertions, 19 deletions
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index 0f6fd42f55ca..03ec76fc22ff 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -18,6 +18,7 @@
*/
#include <linux/init.h>
+#include <linux/iopoll.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/bitops.h>
@@ -385,6 +386,7 @@ struct sdma_engine {
const struct sdma_driver_data *drvdata;
u32 spba_start_addr;
u32 spba_end_addr;
+ unsigned int irq;
};
static struct sdma_driver_data sdma_imx31 = {
@@ -571,28 +573,20 @@ static void sdma_enable_channel(struct sdma_engine *sdma, int channel)
static int sdma_run_channel0(struct sdma_engine *sdma)
{
int ret;
- unsigned long timeout = 500;
+ u32 reg;
sdma_enable_channel(sdma, 0);
- while (!(ret = readl_relaxed(sdma->regs + SDMA_H_INTR) & 1)) {
- if (timeout-- <= 0)
- break;
- udelay(1);
- }
-
- if (ret) {
- /* Clear the interrupt status */
- writel_relaxed(ret, sdma->regs + SDMA_H_INTR);
- } else {
+ ret = readl_relaxed_poll_timeout_atomic(sdma->regs + SDMA_H_STATSTOP,
+ reg, !(reg & 1), 1, 500);
+ if (ret)
dev_err(sdma->dev, "Timeout waiting for CH0 ready\n");
- }
/* Set bits of CONFIG register with dynamic context switching */
if (readl(sdma->regs + SDMA_H_CONFIG) == 0)
writel_relaxed(SDMA_H_CONFIG_CSM, sdma->regs + SDMA_H_CONFIG);
- return ret ? 0 : -ETIMEDOUT;
+ return ret;
}
static int sdma_load_script(struct sdma_engine *sdma, void *buf, int size,
@@ -727,9 +721,9 @@ static irqreturn_t sdma_int_handler(int irq, void *dev_id)
unsigned long stat;
stat = readl_relaxed(sdma->regs + SDMA_H_INTR);
- /* not interested in channel 0 interrupts */
- stat &= ~1;
writel_relaxed(stat, sdma->regs + SDMA_H_INTR);
+ /* channel 0 is special and not handled here, see run_channel0() */
+ stat &= ~1;
while (stat) {
int channel = fls(stat) - 1;
@@ -758,7 +752,7 @@ static void sdma_get_pc(struct sdma_channel *sdmac,
* These are needed once we start to support transfers between
* two peripherals or memory-to-memory transfers
*/
- int per_2_per = 0, emi_2_emi = 0;
+ int per_2_per = 0;
sdmac->pc_from_device = 0;
sdmac->pc_to_device = 0;
@@ -766,7 +760,6 @@ static void sdma_get_pc(struct sdma_channel *sdmac,
switch (peripheral_type) {
case IMX_DMATYPE_MEMORY:
- emi_2_emi = sdma->script_addrs->ap_2_ap_addr;
break;
case IMX_DMATYPE_DSP:
emi_2_per = sdma->script_addrs->bp_2_ap_addr;
@@ -999,8 +992,6 @@ static int sdma_config_channel(struct dma_chan *chan)
} else
__set_bit(sdmac->event_id0, sdmac->event_mask);
- /* Watermark Level */
- sdmac->watermark_level |= sdmac->watermark_level;
/* Address */
sdmac->shp_addr = sdmac->per_address;
sdmac->per_addr = sdmac->per_address2;
@@ -1715,6 +1706,8 @@ static int sdma_probe(struct platform_device *pdev)
if (ret)
return ret;
+ sdma->irq = irq;
+
sdma->script_addrs = kzalloc(sizeof(*sdma->script_addrs), GFP_KERNEL);
if (!sdma->script_addrs)
return -ENOMEM;
@@ -1840,6 +1833,7 @@ static int sdma_remove(struct platform_device *pdev)
struct sdma_engine *sdma = platform_get_drvdata(pdev);
int i;
+ devm_free_irq(&pdev->dev, sdma->irq, sdma);
dma_async_device_unregister(&sdma->dma_device);
kfree(sdma->script_addrs);
/* Kill the tasklet */