aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/dma/dma.txt81
-rw-r--r--drivers/of/Makefile2
-rw-r--r--drivers/of/dma.c219
-rw-r--r--include/linux/of_dma.h45
4 files changed, 346 insertions, 1 deletions
diff --git a/Documentation/devicetree/bindings/dma/dma.txt b/Documentation/devicetree/bindings/dma/dma.txt
new file mode 100644
index 000000000000..a4f59a5967d4
--- /dev/null
+++ b/Documentation/devicetree/bindings/dma/dma.txt
@@ -0,0 +1,81 @@
1* Generic DMA Controller and DMA request bindings
2
3Generic binding to provide a way for a driver using DMA Engine to retrieve the
4DMA request or channel information that goes from a hardware device to a DMA
5controller.
6
7
8* DMA controller
9
10Required property:
11- #dma-cells: Must be at least 1. Used to provide DMA controller
12 specific information. See DMA client binding below for
13 more details.
14
15Optional properties:
16- #dma-channels: Number of DMA channels supported by the controller.
17- #dma-requests: Number of DMA requests signals supported by the
18 controller.
19
20Example:
21
22 dma: dma@48000000 {
23 compatible = "ti,omap-sdma"
24 reg = <0x48000000 0x1000>;
25 interrupts = <0 12 0x4
26 0 13 0x4
27 0 14 0x4
28 0 15 0x4>;
29 #dma-cells = <1>;
30 #dma-channels = <32>;
31 #dma-requests = <127>;
32 };
33
34
35* DMA client
36
37Client drivers should specify the DMA property using a phandle to the controller
38followed by DMA controller specific data.
39
40Required property:
41- dmas: List of one or more DMA specifiers, each consisting of
42 - A phandle pointing to DMA controller node
43 - A number of integer cells, as determined by the
44 #dma-cells property in the node referenced by phandle
45 containing DMA controller specific information. This
46 typically contains a DMA request line number or a
47 channel number, but can contain any data that is used
48 required for configuring a channel.
49- dma-names: Contains one identifier string for each DMA specifier in
50 the dmas property. The specific strings that can be used
51 are defined in the binding of the DMA client device.
52 Multiple DMA specifiers can be used to represent
53 alternatives and in this case the dma-names for those
54 DMA specifiers must be identical (see examples).
55
56Examples:
57
581. A device with one DMA read channel, one DMA write channel:
59
60 i2c1: i2c@1 {
61 ...
62 dmas = <&dma 2 /* read channel */
63 &dma 3>; /* write channel */
64 dma-names = "rx", "tx"
65 ...
66 };
67
682. A single read-write channel with three alternative DMA controllers:
69
70 dmas = <&dma1 5
71 &dma2 7
72 &dma3 2>;
73 dma-names = "rx-tx", "rx-tx", "rx-tx"
74
753. A device with three channels, one of which has two alternatives:
76
77 dmas = <&dma1 2 /* read channel */
78 &dma1 3 /* write channel */
79 &dma2 0 /* error read */
80 &dma3 0>; /* alternative error read */
81 dma-names = "rx", "tx", "error", "error";
diff --git a/drivers/of/Makefile b/drivers/of/Makefile
index e027f444d10c..eafa107aed40 100644
--- a/drivers/of/Makefile
+++ b/drivers/of/Makefile
@@ -1,4 +1,4 @@
1obj-y = base.o 1obj-y = base.o dma.o
2obj-$(CONFIG_OF_FLATTREE) += fdt.o 2obj-$(CONFIG_OF_FLATTREE) += fdt.o
3obj-$(CONFIG_OF_PROMTREE) += pdt.o 3obj-$(CONFIG_OF_PROMTREE) += pdt.o
4obj-$(CONFIG_OF_ADDRESS) += address.o 4obj-$(CONFIG_OF_ADDRESS) += address.o
diff --git a/drivers/of/dma.c b/drivers/of/dma.c
new file mode 100644
index 000000000000..19ad37c066f5
--- /dev/null
+++ b/drivers/of/dma.c
@@ -0,0 +1,219 @@
1/*
2 * Device tree helpers for DMA request / controller
3 *
4 * Based on of_gpio.c
5 *
6 * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/device.h>
14#include <linux/err.h>
15#include <linux/module.h>
16#include <linux/rculist.h>
17#include <linux/slab.h>
18#include <linux/of.h>
19#include <linux/of_dma.h>
20
21static LIST_HEAD(of_dma_list);
22
23/**
24 * of_dma_find_controller - Find a DMA controller in DT DMA helpers list
25 * @np: device node of DMA controller
26 */
27static struct of_dma *of_dma_find_controller(struct device_node *np)
28{
29 struct of_dma *ofdma;
30
31 if (list_empty(&of_dma_list)) {
32 pr_err("empty DMA controller list\n");
33 return NULL;
34 }
35
36 list_for_each_entry_rcu(ofdma, &of_dma_list, of_dma_controllers)
37 if (ofdma->of_node == np)
38 return ofdma;
39
40 return NULL;
41}
42
43/**
44 * of_dma_controller_register - Register a DMA controller to DT DMA helpers
45 * @np: device node of DMA controller
46 * @of_dma_xlate: translation function which converts a phandle
47 * arguments list into a dma_chan structure
48 * @data pointer to controller specific data to be used by
49 * translation function
50 *
51 * Returns 0 on success or appropriate errno value on error.
52 *
53 * Allocated memory should be freed with appropriate of_dma_controller_free()
54 * call.
55 */
56int of_dma_controller_register(struct device_node *np,
57 struct dma_chan *(*of_dma_xlate)
58 (struct of_phandle_args *, struct of_dma *),
59 void *data)
60{
61 struct of_dma *ofdma;
62 int nbcells;
63
64 if (!np || !of_dma_xlate) {
65 pr_err("%s: not enough information provided\n", __func__);
66 return -EINVAL;
67 }
68
69 ofdma = kzalloc(sizeof(*ofdma), GFP_KERNEL);
70 if (!ofdma)
71 return -ENOMEM;
72
73 nbcells = be32_to_cpup(of_get_property(np, "#dma-cells", NULL));
74 if (!nbcells) {
75 pr_err("%s: #dma-cells property is missing or invalid\n",
76 __func__);
77 return -EINVAL;
78 }
79
80 ofdma->of_node = np;
81 ofdma->of_dma_nbcells = nbcells;
82 ofdma->of_dma_xlate = of_dma_xlate;
83 ofdma->of_dma_data = data;
84
85 /* Now queue of_dma controller structure in list */
86 list_add_tail_rcu(&ofdma->of_dma_controllers, &of_dma_list);
87
88 return 0;
89}
90EXPORT_SYMBOL_GPL(of_dma_controller_register);
91
92/**
93 * of_dma_controller_free - Remove a DMA controller from DT DMA helpers list
94 * @np: device node of DMA controller
95 *
96 * Memory allocated by of_dma_controller_register() is freed here.
97 */
98void of_dma_controller_free(struct device_node *np)
99{
100 struct of_dma *ofdma;
101
102 ofdma = of_dma_find_controller(np);
103 if (ofdma) {
104 list_del_rcu(&ofdma->of_dma_controllers);
105 kfree(ofdma);
106 }
107}
108EXPORT_SYMBOL_GPL(of_dma_controller_free);
109
110/**
111 * of_dma_find_channel - Find a DMA channel by name
112 * @np: device node to look for DMA channels
113 * @name: name of desired channel
114 * @dma_spec: pointer to DMA specifier as found in the device tree
115 *
116 * Find a DMA channel by the name. Returns 0 on success or appropriate
117 * errno value on error.
118 */
119static int of_dma_find_channel(struct device_node *np, char *name,
120 struct of_phandle_args *dma_spec)
121{
122 int count, i;
123 const char *s;
124
125 count = of_property_count_strings(np, "dma-names");
126 if (count < 0)
127 return count;
128
129 for (i = 0; i < count; i++) {
130 if (of_property_read_string_index(np, "dma-names", i, &s))
131 continue;
132
133 if (strcmp(name, s))
134 continue;
135
136 if (!of_parse_phandle_with_args(np, "dmas", "#dma-cells", i,
137 dma_spec))
138 return 0;
139 }
140
141 return -ENODEV;
142}
143
144/**
145 * of_dma_request_slave_channel - Get the DMA slave channel
146 * @np: device node to get DMA request from
147 * @name: name of desired channel
148 *
149 * Returns pointer to appropriate dma channel on success or NULL on error.
150 */
151struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
152 char *name)
153{
154 struct of_phandle_args dma_spec;
155 struct of_dma *ofdma;
156 struct dma_chan *chan;
157 int r;
158
159 if (!np || !name) {
160 pr_err("%s: not enough information provided\n", __func__);
161 return NULL;
162 }
163
164 do {
165 r = of_dma_find_channel(np, name, &dma_spec);
166 if (r) {
167 pr_err("%s: can't find DMA channel\n", np->full_name);
168 return NULL;
169 }
170
171 ofdma = of_dma_find_controller(dma_spec.np);
172 if (!ofdma) {
173 pr_debug("%s: can't find DMA controller %s\n",
174 np->full_name, dma_spec.np->full_name);
175 continue;
176 }
177
178 if (dma_spec.args_count != ofdma->of_dma_nbcells) {
179 pr_debug("%s: wrong #dma-cells for %s\n", np->full_name,
180 dma_spec.np->full_name);
181 continue;
182 }
183
184 chan = ofdma->of_dma_xlate(&dma_spec, ofdma);
185
186 of_node_put(dma_spec.np);
187
188 } while (!chan);
189
190 return chan;
191}
192
193/**
194 * of_dma_simple_xlate - Simple DMA engine translation function
195 * @dma_spec: pointer to DMA specifier as found in the device tree
196 * @of_dma: pointer to DMA controller data
197 *
198 * A simple translation function for devices that use a 32-bit value for the
199 * filter_param when calling the DMA engine dma_request_channel() function.
200 * Note that this translation function requires that #dma-cells is equal to 1
201 * and the argument of the dma specifier is the 32-bit filter_param. Returns
202 * pointer to appropriate dma channel on success or NULL on error.
203 */
204struct dma_chan *of_dma_simple_xlate(struct of_phandle_args *dma_spec,
205 struct of_dma *ofdma)
206{
207 int count = dma_spec->args_count;
208 struct of_dma_filter_info *info = ofdma->of_dma_data;
209
210 if (!info || !info->filter_fn)
211 return NULL;
212
213 if (count != 1)
214 return NULL;
215
216 return dma_request_channel(info->dma_cap, info->filter_fn,
217 &dma_spec->args[0]);
218}
219EXPORT_SYMBOL_GPL(of_dma_simple_xlate);
diff --git a/include/linux/of_dma.h b/include/linux/of_dma.h
new file mode 100644
index 000000000000..337823dc6b90
--- /dev/null
+++ b/include/linux/of_dma.h
@@ -0,0 +1,45 @@
1/*
2 * OF helpers for DMA request / controller
3 *
4 * Based on of_gpio.h
5 *
6 * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#ifndef __LINUX_OF_DMA_H
14#define __LINUX_OF_DMA_H
15
16#include <linux/of.h>
17#include <linux/dmaengine.h>
18
19struct device_node;
20
21struct of_dma {
22 struct list_head of_dma_controllers;
23 struct device_node *of_node;
24 int of_dma_nbcells;
25 struct dma_chan *(*of_dma_xlate)
26 (struct of_phandle_args *, struct of_dma *);
27 void *of_dma_data;
28};
29
30struct of_dma_filter_info {
31 dma_cap_mask_t dma_cap;
32 dma_filter_fn filter_fn;
33};
34
35extern int of_dma_controller_register(struct device_node *np,
36 struct dma_chan *(*of_dma_xlate)
37 (struct of_phandle_args *, struct of_dma *),
38 void *data);
39extern void of_dma_controller_free(struct device_node *np);
40extern struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
41 char *name);
42extern struct dma_chan *of_dma_simple_xlate(struct of_phandle_args *dma_spec,
43 struct of_dma *ofdma);
44
45#endif /* __LINUX_OF_DMA_H */