diff options
author | Stephen Warren <swarren@nvidia.com> | 2013-11-11 15:09:35 -0500 |
---|---|---|
committer | Stephen Warren <swarren@nvidia.com> | 2013-12-11 18:43:27 -0500 |
commit | 996556c92a706058cf5ce6b3ef8dacc4032a3e0d (patch) | |
tree | 8a0df4fe6165488e9f1f218cea50cc5043d1a277 | |
parent | 9aa433d2a77220fc261cb8248bb93bdd8e3944ef (diff) |
dma: tegra: register as an OF DMA controller
Call of_dma_controller_register() so that DMA clients can look up the
Tegra DMA controller using standard APIs. This requires the of_xlate()
function to save off the DMA slave ID, and for tegra_dma_slave_config()
not to over-write this information; once DMA client drivers are converted
to dma_request_slave_channel() and DT-based lookups, they won't set this
field of struct dma_slave_config anymore.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Reviewed-by: Thierry Reding <treding@nvidia.com>
-rw-r--r-- | drivers/dma/tegra20-apb-dma.c | 39 |
1 files changed, 36 insertions, 3 deletions
diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c index afa5844c9346..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,6 +29,7 @@ | |||
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> |
@@ -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 | }; |
@@ -340,6 +342,8 @@ static int tegra_dma_slave_config(struct dma_chan *dc, | |||
340 | } | 342 | } |
341 | 343 | ||
342 | 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; | ||
343 | tdc->config_init = true; | 347 | tdc->config_init = true; |
344 | return 0; | 348 | return 0; |
345 | } | 349 | } |
@@ -942,7 +946,7 @@ static struct dma_async_tx_descriptor *tegra_dma_prep_slave_sg( | |||
942 | ahb_seq |= TEGRA_APBDMA_AHBSEQ_BUS_WIDTH_32; | 946 | ahb_seq |= TEGRA_APBDMA_AHBSEQ_BUS_WIDTH_32; |
943 | 947 | ||
944 | csr |= TEGRA_APBDMA_CSR_ONCE | TEGRA_APBDMA_CSR_FLOW; | 948 | csr |= TEGRA_APBDMA_CSR_ONCE | TEGRA_APBDMA_CSR_FLOW; |
945 | csr |= tdc->dma_sconfig.slave_id << TEGRA_APBDMA_CSR_REQ_SEL_SHIFT; | 949 | csr |= tdc->slave_id << TEGRA_APBDMA_CSR_REQ_SEL_SHIFT; |
946 | if (flags & DMA_PREP_INTERRUPT) | 950 | if (flags & DMA_PREP_INTERRUPT) |
947 | csr |= TEGRA_APBDMA_CSR_IE_EOC; | 951 | csr |= TEGRA_APBDMA_CSR_IE_EOC; |
948 | 952 | ||
@@ -1086,7 +1090,7 @@ static struct dma_async_tx_descriptor *tegra_dma_prep_dma_cyclic( | |||
1086 | csr |= TEGRA_APBDMA_CSR_FLOW; | 1090 | csr |= TEGRA_APBDMA_CSR_FLOW; |
1087 | if (flags & DMA_PREP_INTERRUPT) | 1091 | if (flags & DMA_PREP_INTERRUPT) |
1088 | csr |= TEGRA_APBDMA_CSR_IE_EOC; | 1092 | csr |= TEGRA_APBDMA_CSR_IE_EOC; |
1089 | csr |= tdc->dma_sconfig.slave_id << TEGRA_APBDMA_CSR_REQ_SEL_SHIFT; | 1093 | csr |= tdc->slave_id << TEGRA_APBDMA_CSR_REQ_SEL_SHIFT; |
1090 | 1094 | ||
1091 | apb_seq |= TEGRA_APBDMA_APBSEQ_WRAP_WORD_1; | 1095 | apb_seq |= TEGRA_APBDMA_APBSEQ_WRAP_WORD_1; |
1092 | 1096 | ||
@@ -1206,6 +1210,25 @@ static void tegra_dma_free_chan_resources(struct dma_chan *dc) | |||
1206 | kfree(sg_req); | 1210 | kfree(sg_req); |
1207 | } | 1211 | } |
1208 | clk_disable_unprepare(tdma->dma_clk); | 1212 | clk_disable_unprepare(tdma->dma_clk); |
1213 | |||
1214 | tdc->slave_id = 0; | ||
1215 | } | ||
1216 | |||
1217 | static 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; | ||
1209 | } | 1232 | } |
1210 | 1233 | ||
1211 | /* Tegra20 specific DMA controller information */ | 1234 | /* Tegra20 specific DMA controller information */ |
@@ -1383,10 +1406,20 @@ static int tegra_dma_probe(struct platform_device *pdev) | |||
1383 | goto err_irq; | 1406 | goto err_irq; |
1384 | } | 1407 | } |
1385 | 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 | |||
1386 | 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", |
1387 | cdata->nr_channels); | 1418 | cdata->nr_channels); |
1388 | return 0; | 1419 | return 0; |
1389 | 1420 | ||
1421 | err_unregister_dma_dev: | ||
1422 | dma_async_device_unregister(&tdma->dma_dev); | ||
1390 | err_irq: | 1423 | err_irq: |
1391 | while (--i >= 0) { | 1424 | while (--i >= 0) { |
1392 | struct tegra_dma_channel *tdc = &tdma->channels[i]; | 1425 | struct tegra_dma_channel *tdc = &tdma->channels[i]; |