aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma/imx-dma.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/dma/imx-dma.c')
-rw-r--r--drivers/dma/imx-dma.c77
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
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,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
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;
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
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,