diff options
Diffstat (limited to 'drivers/dma/imx-dma.c')
-rw-r--r-- | drivers/dma/imx-dma.c | 77 |
1 files changed, 76 insertions, 1 deletions
diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c index f28583370d00..ff2aab973b45 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,17 +1019,55 @@ 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; |
1009 | 1069 | ||
1070 | imxdma->dev = &pdev->dev; | ||
1010 | imxdma->devtype = pdev->id_entry->driver_data; | 1071 | imxdma->devtype = pdev->id_entry->driver_data; |
1011 | 1072 | ||
1012 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1073 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
@@ -1111,7 +1172,6 @@ static int __init imxdma_probe(struct platform_device *pdev) | |||
1111 | &imxdma->dma_device.channels); | 1172 | &imxdma->dma_device.channels); |
1112 | } | 1173 | } |
1113 | 1174 | ||
1114 | imxdma->dev = &pdev->dev; | ||
1115 | imxdma->dma_device.dev = &pdev->dev; | 1175 | imxdma->dma_device.dev = &pdev->dev; |
1116 | 1176 | ||
1117 | imxdma->dma_device.device_alloc_chan_resources = imxdma_alloc_chan_resources; | 1177 | imxdma->dma_device.device_alloc_chan_resources = imxdma_alloc_chan_resources; |
@@ -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, |