aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2013-12-26 13:33:05 -0500
committerOlof Johansson <olof@lixom.net>2013-12-26 13:33:05 -0500
commite7d248f0e0f93b86c56466ede82c46234f622615 (patch)
tree36adb8e2ff0b4cc570334372389f82a73e352002 /drivers/dma
parent1c7af42fe579b5cf8c942319cbed38801305dda4 (diff)
parent8a0a1af30cbf56b41220a02e34835022c4d72f41 (diff)
Merge tag 'tegra-for-3.14-dmas-resets-rework' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux into next/cleanup
From Stephen Warren: ARM: tegra: implement common DMA and resets DT bindings This series converts the Tegra DTs and drivers to use the common/ standard DMA and reset bindings, rather than custom bindings. It also adds complete documentation for the Tegra clock bindings without actually changing any binding definitions. This conversion relies on a few sets of patches in branches from outside the Tegra tree: 1) A patch to add an DMA channel request API which allows deferred probe to be implemented. 2) A patch to implement a common part of the of_xlate function for DMA controllers. 3) Some ASoC patches (which in turn rely on (1) above), which support deferred probe during DMA channel allocation. 4) The Tegra clock driver changes for 3.14. Consequently, this branch is based on a merge of all of those external branches. In turn, this branch is or will be pulled into a few places that either rely on features introduced here, or would otherwise conflict with the patches: a) Tegra's own for-3.14/powergate and for-4.14/dt branches, to avoid conflicts. b) The DRM tree, which introduces new code that relies on the reset controller framework introduced in this branch, and to avoid conflicts. * tag 'tegra-for-3.14-dmas-resets-rework' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux: (30 commits) spi: tegra: checking for ERR_PTR instead of NULL ASoC: tegra: update module reset list for Tegra124 clk: tegra: remove bogus PCIE_XCLK clk: tegra: remove legacy reset APIs ARM: tegra: remove legacy DMA entries from DT ARM: tegra: remove legacy clock entries from DT USB: EHCI: tegra: use reset framework Input: tegra-kbc - use reset framework serial: tegra: convert to standard DMA DT bindings serial: tegra: use reset framework spi: tegra: convert to standard DMA DT bindings spi: tegra: use reset framework staging: nvec: use reset framework i2c: tegra: use reset framework ASoC: tegra: convert to standard DMA DT bindings ASoC: tegra: allocate AHUB FIFO during probe() not startup() ASoC: tegra: call pm_runtime APIs around register accesses ASoC: tegra: use reset framework dma: tegra: register as an OF DMA controller dma: tegra: use reset framework ... Signed-off-by: Olof Johansson <olof@lixom.net>
Diffstat (limited to 'drivers/dma')
-rw-r--r--drivers/dma/tegra20-apb-dma.c52
1 files changed, 46 insertions, 6 deletions
diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c
index 73654e33f13b..d11bb3620f27 100644
--- a/drivers/dma/tegra20-apb-dma.c
+++ b/drivers/dma/tegra20-apb-dma.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * DMA driver for Nvidia's Tegra20 APB DMA controller. 2 * DMA driver for Nvidia's Tegra20 APB DMA controller.
3 * 3 *
4 * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. 4 * Copyright (c) 2012-2013, NVIDIA CORPORATION. All rights reserved.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify it 6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License, 7 * under the terms and conditions of the GNU General Public License,
@@ -29,11 +29,12 @@
29#include <linux/module.h> 29#include <linux/module.h>
30#include <linux/of.h> 30#include <linux/of.h>
31#include <linux/of_device.h> 31#include <linux/of_device.h>
32#include <linux/of_dma.h>
32#include <linux/platform_device.h> 33#include <linux/platform_device.h>
33#include <linux/pm.h> 34#include <linux/pm.h>
34#include <linux/pm_runtime.h> 35#include <linux/pm_runtime.h>
36#include <linux/reset.h>
35#include <linux/slab.h> 37#include <linux/slab.h>
36#include <linux/clk/tegra.h>
37 38
38#include "dmaengine.h" 39#include "dmaengine.h"
39 40
@@ -199,6 +200,7 @@ struct tegra_dma_channel {
199 void *callback_param; 200 void *callback_param;
200 201
201 /* Channel-slave specific configuration */ 202 /* Channel-slave specific configuration */
203 unsigned int slave_id;
202 struct dma_slave_config dma_sconfig; 204 struct dma_slave_config dma_sconfig;
203 struct tegra_dma_channel_regs channel_reg; 205 struct tegra_dma_channel_regs channel_reg;
204}; 206};
@@ -208,6 +210,7 @@ struct tegra_dma {
208 struct dma_device dma_dev; 210 struct dma_device dma_dev;
209 struct device *dev; 211 struct device *dev;
210 struct clk *dma_clk; 212 struct clk *dma_clk;
213 struct reset_control *rst;
211 spinlock_t global_lock; 214 spinlock_t global_lock;
212 void __iomem *base_addr; 215 void __iomem *base_addr;
213 const struct tegra_dma_chip_data *chip_data; 216 const struct tegra_dma_chip_data *chip_data;
@@ -339,6 +342,8 @@ static int tegra_dma_slave_config(struct dma_chan *dc,
339 } 342 }
340 343
341 memcpy(&tdc->dma_sconfig, sconfig, sizeof(*sconfig)); 344 memcpy(&tdc->dma_sconfig, sconfig, sizeof(*sconfig));
345 if (!tdc->slave_id)
346 tdc->slave_id = sconfig->slave_id;
342 tdc->config_init = true; 347 tdc->config_init = true;
343 return 0; 348 return 0;
344} 349}
@@ -941,7 +946,7 @@ static struct dma_async_tx_descriptor *tegra_dma_prep_slave_sg(
941 ahb_seq |= TEGRA_APBDMA_AHBSEQ_BUS_WIDTH_32; 946 ahb_seq |= TEGRA_APBDMA_AHBSEQ_BUS_WIDTH_32;
942 947
943 csr |= TEGRA_APBDMA_CSR_ONCE | TEGRA_APBDMA_CSR_FLOW; 948 csr |= TEGRA_APBDMA_CSR_ONCE | TEGRA_APBDMA_CSR_FLOW;
944 csr |= tdc->dma_sconfig.slave_id << TEGRA_APBDMA_CSR_REQ_SEL_SHIFT; 949 csr |= tdc->slave_id << TEGRA_APBDMA_CSR_REQ_SEL_SHIFT;
945 if (flags & DMA_PREP_INTERRUPT) 950 if (flags & DMA_PREP_INTERRUPT)
946 csr |= TEGRA_APBDMA_CSR_IE_EOC; 951 csr |= TEGRA_APBDMA_CSR_IE_EOC;
947 952
@@ -1085,7 +1090,7 @@ static struct dma_async_tx_descriptor *tegra_dma_prep_dma_cyclic(
1085 csr |= TEGRA_APBDMA_CSR_FLOW; 1090 csr |= TEGRA_APBDMA_CSR_FLOW;
1086 if (flags & DMA_PREP_INTERRUPT) 1091 if (flags & DMA_PREP_INTERRUPT)
1087 csr |= TEGRA_APBDMA_CSR_IE_EOC; 1092 csr |= TEGRA_APBDMA_CSR_IE_EOC;
1088 csr |= tdc->dma_sconfig.slave_id << TEGRA_APBDMA_CSR_REQ_SEL_SHIFT; 1093 csr |= tdc->slave_id << TEGRA_APBDMA_CSR_REQ_SEL_SHIFT;
1089 1094
1090 apb_seq |= TEGRA_APBDMA_APBSEQ_WRAP_WORD_1; 1095 apb_seq |= TEGRA_APBDMA_APBSEQ_WRAP_WORD_1;
1091 1096
@@ -1205,6 +1210,25 @@ static void tegra_dma_free_chan_resources(struct dma_chan *dc)
1205 kfree(sg_req); 1210 kfree(sg_req);
1206 } 1211 }
1207 clk_disable_unprepare(tdma->dma_clk); 1212 clk_disable_unprepare(tdma->dma_clk);
1213
1214 tdc->slave_id = 0;
1215}
1216
1217static struct dma_chan *tegra_dma_of_xlate(struct of_phandle_args *dma_spec,
1218 struct of_dma *ofdma)
1219{
1220 struct tegra_dma *tdma = ofdma->of_dma_data;
1221 struct dma_chan *chan;
1222 struct tegra_dma_channel *tdc;
1223
1224 chan = dma_get_any_slave_channel(&tdma->dma_dev);
1225 if (!chan)
1226 return NULL;
1227
1228 tdc = to_tegra_dma_chan(chan);
1229 tdc->slave_id = dma_spec->args[0];
1230
1231 return chan;
1208} 1232}
1209 1233
1210/* Tegra20 specific DMA controller information */ 1234/* Tegra20 specific DMA controller information */
@@ -1282,6 +1306,12 @@ static int tegra_dma_probe(struct platform_device *pdev)
1282 return PTR_ERR(tdma->dma_clk); 1306 return PTR_ERR(tdma->dma_clk);
1283 } 1307 }
1284 1308
1309 tdma->rst = devm_reset_control_get(&pdev->dev, "dma");
1310 if (IS_ERR(tdma->rst)) {
1311 dev_err(&pdev->dev, "Error: Missing reset\n");
1312 return PTR_ERR(tdma->rst);
1313 }
1314
1285 spin_lock_init(&tdma->global_lock); 1315 spin_lock_init(&tdma->global_lock);
1286 1316
1287 pm_runtime_enable(&pdev->dev); 1317 pm_runtime_enable(&pdev->dev);
@@ -1302,9 +1332,9 @@ static int tegra_dma_probe(struct platform_device *pdev)
1302 } 1332 }
1303 1333
1304 /* Reset DMA controller */ 1334 /* Reset DMA controller */
1305 tegra_periph_reset_assert(tdma->dma_clk); 1335 reset_control_assert(tdma->rst);
1306 udelay(2); 1336 udelay(2);
1307 tegra_periph_reset_deassert(tdma->dma_clk); 1337 reset_control_deassert(tdma->rst);
1308 1338
1309 /* Enable global DMA registers */ 1339 /* Enable global DMA registers */
1310 tdma_write(tdma, TEGRA_APBDMA_GENERAL, TEGRA_APBDMA_GENERAL_ENABLE); 1340 tdma_write(tdma, TEGRA_APBDMA_GENERAL, TEGRA_APBDMA_GENERAL_ENABLE);
@@ -1376,10 +1406,20 @@ static int tegra_dma_probe(struct platform_device *pdev)
1376 goto err_irq; 1406 goto err_irq;
1377 } 1407 }
1378 1408
1409 ret = of_dma_controller_register(pdev->dev.of_node,
1410 tegra_dma_of_xlate, tdma);
1411 if (ret < 0) {
1412 dev_err(&pdev->dev,
1413 "Tegra20 APB DMA OF registration failed %d\n", ret);
1414 goto err_unregister_dma_dev;
1415 }
1416
1379 dev_info(&pdev->dev, "Tegra20 APB DMA driver register %d channels\n", 1417 dev_info(&pdev->dev, "Tegra20 APB DMA driver register %d channels\n",
1380 cdata->nr_channels); 1418 cdata->nr_channels);
1381 return 0; 1419 return 0;
1382 1420
1421err_unregister_dma_dev:
1422 dma_async_device_unregister(&tdma->dma_dev);
1383err_irq: 1423err_irq:
1384 while (--i >= 0) { 1424 while (--i >= 0) {
1385 struct tegra_dma_channel *tdc = &tdma->channels[i]; 1425 struct tegra_dma_channel *tdc = &tdma->channels[i];