aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/dma/fsl-imx-dma.txt48
-rw-r--r--drivers/dma/imx-dma.c75
-rw-r--r--include/linux/platform_data/dma-imx.h6
3 files changed, 125 insertions, 4 deletions
diff --git a/Documentation/devicetree/bindings/dma/fsl-imx-dma.txt b/Documentation/devicetree/bindings/dma/fsl-imx-dma.txt
new file mode 100644
index 000000000000..2717ecb47db9
--- /dev/null
+++ b/Documentation/devicetree/bindings/dma/fsl-imx-dma.txt
@@ -0,0 +1,48 @@
1* Freescale Direct Memory Access (DMA) Controller for i.MX
2
3This document will only describe differences to the generic DMA Controller and
4DMA request bindings as described in dma/dma.txt .
5
6* DMA controller
7
8Required properties:
9- compatible : Should be "fsl,<chip>-dma". chip can be imx1, imx21 or imx27
10- reg : Should contain DMA registers location and length
11- interrupts : First item should be DMA interrupt, second one is optional and
12 should contain DMA Error interrupt
13- #dma-cells : Has to be 1. imx-dma does not support anything else.
14
15Optional properties:
16- #dma-channels : Number of DMA channels supported. Should be 16.
17- #dma-requests : Number of DMA requests supported.
18
19Example:
20
21 dma: dma@10001000 {
22 compatible = "fsl,imx27-dma";
23 reg = <0x10001000 0x1000>;
24 interrupts = <32 33>;
25 #dma-cells = <1>;
26 #dma-channels = <16>;
27 };
28
29
30* DMA client
31
32Clients have to specify the DMA requests with phandles in a list.
33
34Required properties:
35- dmas: List of one or more DMA request specifiers. One DMA request specifier
36 consists of a phandle to the DMA controller followed by the integer
37 specifiying the request line.
38- dma-names: List of string identifiers for the DMA requests. For the correct
39 names, have a look at the specific client driver.
40
41Example:
42
43 sdhci1: sdhci@10013000 {
44 ...
45 dmas = <&dma 7>;
46 dma-names = "rx-tx";
47 ...
48 };
diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c
index f28583370d00..34c54cf08231 100644
--- a/drivers/dma/imx-dma.c
+++ b/drivers/dma/imx-dma.c
@@ -27,6 +27,8 @@
27#include <linux/clk.h> 27#include <linux/clk.h>
28#include <linux/dmaengine.h> 28#include <linux/dmaengine.h>
29#include <linux/module.h> 29#include <linux/module.h>
30#include <linux/of_device.h>
31#include <linux/of_dma.h>
30 32
31#include <asm/irq.h> 33#include <asm/irq.h>
32#include <linux/platform_data/dma-imx.h> 34#include <linux/platform_data/dma-imx.h>
@@ -186,6 +188,11 @@ struct imxdma_engine {
186 enum imx_dma_type devtype; 188 enum imx_dma_type devtype;
187}; 189};
188 190
191struct imxdma_filter_data {
192 struct imxdma_engine *imxdma;
193 int request;
194};
195
189static struct platform_device_id imx_dma_devtype[] = { 196static struct platform_device_id imx_dma_devtype[] = {
190 { 197 {
191 .name = "imx1-dma", 198 .name = "imx1-dma",
@@ -202,6 +209,22 @@ static struct platform_device_id imx_dma_devtype[] = {
202}; 209};
203MODULE_DEVICE_TABLE(platform, imx_dma_devtype); 210MODULE_DEVICE_TABLE(platform, imx_dma_devtype);
204 211
212static const struct of_device_id imx_dma_of_dev_id[] = {
213 {
214 .compatible = "fsl,imx1-dma",
215 .data = &imx_dma_devtype[IMX1_DMA],
216 }, {
217 .compatible = "fsl,imx21-dma",
218 .data = &imx_dma_devtype[IMX21_DMA],
219 }, {
220 .compatible = "fsl,imx27-dma",
221 .data = &imx_dma_devtype[IMX27_DMA],
222 }, {
223 /* sentinel */
224 }
225};
226MODULE_DEVICE_TABLE(of, imx_dma_of_dev_id);
227
205static inline int is_imx1_dma(struct imxdma_engine *imxdma) 228static inline int is_imx1_dma(struct imxdma_engine *imxdma)
206{ 229{
207 return imxdma->devtype == IMX1_DMA; 230 return imxdma->devtype == IMX1_DMA;
@@ -996,13 +1019,50 @@ static void imxdma_issue_pending(struct dma_chan *chan)
996 spin_unlock_irqrestore(&imxdma->lock, flags); 1019 spin_unlock_irqrestore(&imxdma->lock, flags);
997} 1020}
998 1021
1022static bool imxdma_filter_fn(struct dma_chan *chan, void *param)
1023{
1024 struct imxdma_filter_data *fdata = param;
1025 struct imxdma_channel *imxdma_chan = to_imxdma_chan(chan);
1026
1027 if (chan->device->dev != fdata->imxdma->dev)
1028 return false;
1029
1030 imxdma_chan->dma_request = fdata->request;
1031 chan->private = NULL;
1032
1033 return true;
1034}
1035
1036static struct dma_chan *imxdma_xlate(struct of_phandle_args *dma_spec,
1037 struct of_dma *ofdma)
1038{
1039 int count = dma_spec->args_count;
1040 struct imxdma_engine *imxdma = ofdma->of_dma_data;
1041 struct imxdma_filter_data fdata = {
1042 .imxdma = imxdma,
1043 };
1044
1045 if (count != 1)
1046 return NULL;
1047
1048 fdata.request = dma_spec->args[0];
1049
1050 return dma_request_channel(imxdma->dma_device.cap_mask,
1051 imxdma_filter_fn, &fdata);
1052}
1053
999static int __init imxdma_probe(struct platform_device *pdev) 1054static int __init imxdma_probe(struct platform_device *pdev)
1000 { 1055 {
1001 struct imxdma_engine *imxdma; 1056 struct imxdma_engine *imxdma;
1002 struct resource *res; 1057 struct resource *res;
1058 const struct of_device_id *of_id;
1003 int ret, i; 1059 int ret, i;
1004 int irq, irq_err; 1060 int irq, irq_err;
1005 1061
1062 of_id = of_match_device(imx_dma_of_dev_id, &pdev->dev);
1063 if (of_id)
1064 pdev->id_entry = of_id->data;
1065
1006 imxdma = devm_kzalloc(&pdev->dev, sizeof(*imxdma), GFP_KERNEL); 1066 imxdma = devm_kzalloc(&pdev->dev, sizeof(*imxdma), GFP_KERNEL);
1007 if (!imxdma) 1067 if (!imxdma)
1008 return -ENOMEM; 1068 return -ENOMEM;
@@ -1136,8 +1196,19 @@ static int __init imxdma_probe(struct platform_device *pdev)
1136 goto err; 1196 goto err;
1137 } 1197 }
1138 1198
1199 if (pdev->dev.of_node) {
1200 ret = of_dma_controller_register(pdev->dev.of_node,
1201 imxdma_xlate, imxdma);
1202 if (ret) {
1203 dev_err(&pdev->dev, "unable to register of_dma_controller\n");
1204 goto err_of_dma_controller;
1205 }
1206 }
1207
1139 return 0; 1208 return 0;
1140 1209
1210err_of_dma_controller:
1211 dma_async_device_unregister(&imxdma->dma_device);
1141err: 1212err:
1142 clk_disable_unprepare(imxdma->dma_ipg); 1213 clk_disable_unprepare(imxdma->dma_ipg);
1143 clk_disable_unprepare(imxdma->dma_ahb); 1214 clk_disable_unprepare(imxdma->dma_ahb);
@@ -1150,6 +1221,9 @@ static int imxdma_remove(struct platform_device *pdev)
1150 1221
1151 dma_async_device_unregister(&imxdma->dma_device); 1222 dma_async_device_unregister(&imxdma->dma_device);
1152 1223
1224 if (pdev->dev.of_node)
1225 of_dma_controller_free(pdev->dev.of_node);
1226
1153 clk_disable_unprepare(imxdma->dma_ipg); 1227 clk_disable_unprepare(imxdma->dma_ipg);
1154 clk_disable_unprepare(imxdma->dma_ahb); 1228 clk_disable_unprepare(imxdma->dma_ahb);
1155 1229
@@ -1159,6 +1233,7 @@ static int imxdma_remove(struct platform_device *pdev)
1159static struct platform_driver imxdma_driver = { 1233static struct platform_driver imxdma_driver = {
1160 .driver = { 1234 .driver = {
1161 .name = "imx-dma", 1235 .name = "imx-dma",
1236 .of_match_table = imx_dma_of_dev_id,
1162 }, 1237 },
1163 .id_table = imx_dma_devtype, 1238 .id_table = imx_dma_devtype,
1164 .remove = imxdma_remove, 1239 .remove = imxdma_remove,
diff --git a/include/linux/platform_data/dma-imx.h b/include/linux/platform_data/dma-imx.h
index f6d30cc1cb77..beac6b8b6a7b 100644
--- a/include/linux/platform_data/dma-imx.h
+++ b/include/linux/platform_data/dma-imx.h
@@ -60,10 +60,8 @@ static inline int imx_dma_is_ipu(struct dma_chan *chan)
60 60
61static inline int imx_dma_is_general_purpose(struct dma_chan *chan) 61static inline int imx_dma_is_general_purpose(struct dma_chan *chan)
62{ 62{
63 return strstr(dev_name(chan->device->dev), "sdma") || 63 return !strcmp(chan->device->dev->driver->name, "imx-sdma") ||
64 !strcmp(dev_name(chan->device->dev), "imx1-dma") || 64 !strcmp(chan->device->dev->driver->name, "imx-dma");
65 !strcmp(dev_name(chan->device->dev), "imx21-dma") ||
66 !strcmp(dev_name(chan->device->dev), "imx27-dma");
67} 65}
68 66
69#endif 67#endif