Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

dma: imx-dma: Add oftree support

Adding devicetree support for imx-dma driver. Use driver name for
function 'imx_dma_is_general_purpose' because the devicename for
devicetree initialized devices is different.

Signed-off-by: Markus Pargmann <mpa@pengutronix.de>
Reviewed-by: Arnd Bergmann <arnd@arndb.de>
Reviewed-by: Shawn Guo <shawn.guo@linaro.org>
Acked-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>

authored by

Markus Pargmann and committed by
Vinod Koul
290ad0f9 8552bb4f

+125 -4
+48
Documentation/devicetree/bindings/dma/fsl-imx-dma.txt
··· 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 + };
+75
drivers/dma/imx-dma.c
··· 27 27 #include <linux/clk.h> 28 28 #include <linux/dmaengine.h> 29 29 #include <linux/module.h> 30 + #include <linux/of_device.h> 31 + #include <linux/of_dma.h> 30 32 31 33 #include <asm/irq.h> 32 34 #include <linux/platform_data/dma-imx.h> ··· 188 186 enum imx_dma_type devtype; 189 187 }; 190 188 189 + struct imxdma_filter_data { 190 + struct imxdma_engine *imxdma; 191 + int request; 192 + }; 193 + 191 194 static struct platform_device_id imx_dma_devtype[] = { 192 195 { 193 196 .name = "imx1-dma", ··· 208 201 } 209 202 }; 210 203 MODULE_DEVICE_TABLE(platform, imx_dma_devtype); 204 + 205 + static const struct of_device_id imx_dma_of_dev_id[] = { 206 + { 207 + .compatible = "fsl,imx1-dma", 208 + .data = &imx_dma_devtype[IMX1_DMA], 209 + }, { 210 + .compatible = "fsl,imx21-dma", 211 + .data = &imx_dma_devtype[IMX21_DMA], 212 + }, { 213 + .compatible = "fsl,imx27-dma", 214 + .data = &imx_dma_devtype[IMX27_DMA], 215 + }, { 216 + /* sentinel */ 217 + } 218 + }; 219 + MODULE_DEVICE_TABLE(of, imx_dma_of_dev_id); 211 220 212 221 static inline int is_imx1_dma(struct imxdma_engine *imxdma) 213 222 { ··· 1019 996 spin_unlock_irqrestore(&imxdma->lock, flags); 1020 997 } 1021 998 999 + static bool imxdma_filter_fn(struct dma_chan *chan, void *param) 1000 + { 1001 + struct imxdma_filter_data *fdata = param; 1002 + struct imxdma_channel *imxdma_chan = to_imxdma_chan(chan); 1003 + 1004 + if (chan->device->dev != fdata->imxdma->dev) 1005 + return false; 1006 + 1007 + imxdma_chan->dma_request = fdata->request; 1008 + chan->private = NULL; 1009 + 1010 + return true; 1011 + } 1012 + 1013 + static struct dma_chan *imxdma_xlate(struct of_phandle_args *dma_spec, 1014 + struct of_dma *ofdma) 1015 + { 1016 + int count = dma_spec->args_count; 1017 + struct imxdma_engine *imxdma = ofdma->of_dma_data; 1018 + struct imxdma_filter_data fdata = { 1019 + .imxdma = imxdma, 1020 + }; 1021 + 1022 + if (count != 1) 1023 + return NULL; 1024 + 1025 + fdata.request = dma_spec->args[0]; 1026 + 1027 + return dma_request_channel(imxdma->dma_device.cap_mask, 1028 + imxdma_filter_fn, &fdata); 1029 + } 1030 + 1022 1031 static int __init imxdma_probe(struct platform_device *pdev) 1023 1032 { 1024 1033 struct imxdma_engine *imxdma; 1025 1034 struct resource *res; 1035 + const struct of_device_id *of_id; 1026 1036 int ret, i; 1027 1037 int irq, irq_err; 1038 + 1039 + of_id = of_match_device(imx_dma_of_dev_id, &pdev->dev); 1040 + if (of_id) 1041 + pdev->id_entry = of_id->data; 1028 1042 1029 1043 imxdma = devm_kzalloc(&pdev->dev, sizeof(*imxdma), GFP_KERNEL); 1030 1044 if (!imxdma) ··· 1196 1136 goto err; 1197 1137 } 1198 1138 1139 + if (pdev->dev.of_node) { 1140 + ret = of_dma_controller_register(pdev->dev.of_node, 1141 + imxdma_xlate, imxdma); 1142 + if (ret) { 1143 + dev_err(&pdev->dev, "unable to register of_dma_controller\n"); 1144 + goto err_of_dma_controller; 1145 + } 1146 + } 1147 + 1199 1148 return 0; 1200 1149 1150 + err_of_dma_controller: 1151 + dma_async_device_unregister(&imxdma->dma_device); 1201 1152 err: 1202 1153 clk_disable_unprepare(imxdma->dma_ipg); 1203 1154 clk_disable_unprepare(imxdma->dma_ahb); ··· 1221 1150 1222 1151 dma_async_device_unregister(&imxdma->dma_device); 1223 1152 1153 + if (pdev->dev.of_node) 1154 + of_dma_controller_free(pdev->dev.of_node); 1155 + 1224 1156 clk_disable_unprepare(imxdma->dma_ipg); 1225 1157 clk_disable_unprepare(imxdma->dma_ahb); 1226 1158 ··· 1233 1159 static struct platform_driver imxdma_driver = { 1234 1160 .driver = { 1235 1161 .name = "imx-dma", 1162 + .of_match_table = imx_dma_of_dev_id, 1236 1163 }, 1237 1164 .id_table = imx_dma_devtype, 1238 1165 .remove = imxdma_remove,
+2 -4
include/linux/platform_data/dma-imx.h
··· 60 60 61 61 static inline int imx_dma_is_general_purpose(struct dma_chan *chan) 62 62 { 63 - return strstr(dev_name(chan->device->dev), "sdma") || 64 - !strcmp(dev_name(chan->device->dev), "imx1-dma") || 65 - !strcmp(dev_name(chan->device->dev), "imx21-dma") || 66 - !strcmp(dev_name(chan->device->dev), "imx27-dma"); 63 + return !strcmp(chan->device->dev->driver->name, "imx-sdma") || 64 + !strcmp(chan->device->dev->driver->name, "imx-dma"); 67 65 } 68 66 69 67 #endif