diff options
-rw-r--r-- | Documentation/devicetree/bindings/dma/fsl-imx-dma.txt | 48 | ||||
-rw-r--r-- | drivers/dma/imx-dma.c | 75 | ||||
-rw-r--r-- | include/linux/platform_data/dma-imx.h | 6 |
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 | |||
3 | This document will only describe differences to the generic DMA Controller and | ||
4 | DMA request bindings as described in dma/dma.txt . | ||
5 | |||
6 | * DMA controller | ||
7 | |||
8 | Required 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 | |||
15 | Optional properties: | ||
16 | - #dma-channels : Number of DMA channels supported. Should be 16. | ||
17 | - #dma-requests : Number of DMA requests supported. | ||
18 | |||
19 | Example: | ||
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 | |||
32 | Clients have to specify the DMA requests with phandles in a list. | ||
33 | |||
34 | Required 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 | |||
41 | Example: | ||
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 | ||
191 | struct imxdma_filter_data { | ||
192 | struct imxdma_engine *imxdma; | ||
193 | int request; | ||
194 | }; | ||
195 | |||
189 | static struct platform_device_id imx_dma_devtype[] = { | 196 | static 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 | }; |
203 | MODULE_DEVICE_TABLE(platform, imx_dma_devtype); | 210 | MODULE_DEVICE_TABLE(platform, imx_dma_devtype); |
204 | 211 | ||
212 | static 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 | }; | ||
226 | MODULE_DEVICE_TABLE(of, imx_dma_of_dev_id); | ||
227 | |||
205 | static inline int is_imx1_dma(struct imxdma_engine *imxdma) | 228 | static 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 | ||
1022 | static 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 | |||
1036 | static 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 | |||
999 | static int __init imxdma_probe(struct platform_device *pdev) | 1054 | static 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 | ||
1210 | err_of_dma_controller: | ||
1211 | dma_async_device_unregister(&imxdma->dma_device); | ||
1141 | err: | 1212 | err: |
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) | |||
1159 | static struct platform_driver imxdma_driver = { | 1233 | static 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 | ||
61 | static inline int imx_dma_is_general_purpose(struct dma_chan *chan) | 61 | static 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 |