1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Device tree helpers for DMA request / controller |
4 | * |
5 | * Based on of_gpio.c |
6 | * |
7 | * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ |
8 | */ |
9 | |
10 | #include <linux/device.h> |
11 | #include <linux/err.h> |
12 | #include <linux/module.h> |
13 | #include <linux/mutex.h> |
14 | #include <linux/slab.h> |
15 | #include <linux/of.h> |
16 | #include <linux/of_dma.h> |
17 | |
18 | #include "dmaengine.h" |
19 | |
20 | static LIST_HEAD(of_dma_list); |
21 | static DEFINE_MUTEX(of_dma_lock); |
22 | |
23 | /** |
24 | * of_dma_find_controller - Get a DMA controller in DT DMA helpers list |
25 | * @dma_spec: pointer to DMA specifier as found in the device tree |
26 | * |
27 | * Finds a DMA controller with matching device node and number for dma cells |
28 | * in a list of registered DMA controllers. If a match is found a valid pointer |
29 | * to the DMA data stored is retuned. A NULL pointer is returned if no match is |
30 | * found. |
31 | */ |
32 | static struct of_dma *of_dma_find_controller(const struct of_phandle_args *dma_spec) |
33 | { |
34 | struct of_dma *ofdma; |
35 | |
36 | list_for_each_entry(ofdma, &of_dma_list, of_dma_controllers) |
37 | if (ofdma->of_node == dma_spec->np) |
38 | return ofdma; |
39 | |
40 | pr_debug("%s: can't find DMA controller %pOF\n" , __func__, |
41 | dma_spec->np); |
42 | |
43 | return NULL; |
44 | } |
45 | |
46 | /** |
47 | * of_dma_router_xlate - translation function for router devices |
48 | * @dma_spec: pointer to DMA specifier as found in the device tree |
49 | * @ofdma: pointer to DMA controller data (router information) |
50 | * |
51 | * The function creates new dma_spec to be passed to the router driver's |
52 | * of_dma_route_allocate() function to prepare a dma_spec which will be used |
53 | * to request channel from the real DMA controller. |
54 | */ |
55 | static struct dma_chan *of_dma_router_xlate(struct of_phandle_args *dma_spec, |
56 | struct of_dma *ofdma) |
57 | { |
58 | struct dma_chan *chan; |
59 | struct of_dma *ofdma_target; |
60 | struct of_phandle_args dma_spec_target; |
61 | void *route_data; |
62 | |
63 | /* translate the request for the real DMA controller */ |
64 | memcpy(&dma_spec_target, dma_spec, sizeof(dma_spec_target)); |
65 | route_data = ofdma->of_dma_route_allocate(&dma_spec_target, ofdma); |
66 | if (IS_ERR(ptr: route_data)) |
67 | return NULL; |
68 | |
69 | ofdma_target = of_dma_find_controller(dma_spec: &dma_spec_target); |
70 | if (!ofdma_target) { |
71 | ofdma->dma_router->route_free(ofdma->dma_router->dev, |
72 | route_data); |
73 | chan = ERR_PTR(error: -EPROBE_DEFER); |
74 | goto err; |
75 | } |
76 | |
77 | chan = ofdma_target->of_dma_xlate(&dma_spec_target, ofdma_target); |
78 | if (IS_ERR_OR_NULL(ptr: chan)) { |
79 | ofdma->dma_router->route_free(ofdma->dma_router->dev, |
80 | route_data); |
81 | } else { |
82 | int ret = 0; |
83 | |
84 | chan->router = ofdma->dma_router; |
85 | chan->route_data = route_data; |
86 | |
87 | if (chan->device->device_router_config) |
88 | ret = chan->device->device_router_config(chan); |
89 | |
90 | if (ret) { |
91 | dma_release_channel(chan); |
92 | chan = ERR_PTR(error: ret); |
93 | } |
94 | } |
95 | |
96 | err: |
97 | /* |
98 | * Need to put the node back since the ofdma->of_dma_route_allocate |
99 | * has taken it for generating the new, translated dma_spec |
100 | */ |
101 | of_node_put(node: dma_spec_target.np); |
102 | return chan; |
103 | } |
104 | |
105 | /** |
106 | * of_dma_controller_register - Register a DMA controller to DT DMA helpers |
107 | * @np: device node of DMA controller |
108 | * @of_dma_xlate: translation function which converts a phandle |
109 | * arguments list into a dma_chan structure |
110 | * @data: pointer to controller specific data to be used by |
111 | * translation function |
112 | * |
113 | * Returns 0 on success or appropriate errno value on error. |
114 | * |
115 | * Allocated memory should be freed with appropriate of_dma_controller_free() |
116 | * call. |
117 | */ |
118 | int of_dma_controller_register(struct device_node *np, |
119 | struct dma_chan *(*of_dma_xlate) |
120 | (struct of_phandle_args *, struct of_dma *), |
121 | void *data) |
122 | { |
123 | struct of_dma *ofdma; |
124 | |
125 | if (!np || !of_dma_xlate) { |
126 | pr_err("%s: not enough information provided\n" , __func__); |
127 | return -EINVAL; |
128 | } |
129 | |
130 | ofdma = kzalloc(size: sizeof(*ofdma), GFP_KERNEL); |
131 | if (!ofdma) |
132 | return -ENOMEM; |
133 | |
134 | ofdma->of_node = np; |
135 | ofdma->of_dma_xlate = of_dma_xlate; |
136 | ofdma->of_dma_data = data; |
137 | |
138 | /* Now queue of_dma controller structure in list */ |
139 | mutex_lock(&of_dma_lock); |
140 | list_add_tail(new: &ofdma->of_dma_controllers, head: &of_dma_list); |
141 | mutex_unlock(lock: &of_dma_lock); |
142 | |
143 | return 0; |
144 | } |
145 | EXPORT_SYMBOL_GPL(of_dma_controller_register); |
146 | |
147 | /** |
148 | * of_dma_controller_free - Remove a DMA controller from DT DMA helpers list |
149 | * @np: device node of DMA controller |
150 | * |
151 | * Memory allocated by of_dma_controller_register() is freed here. |
152 | */ |
153 | void of_dma_controller_free(struct device_node *np) |
154 | { |
155 | struct of_dma *ofdma; |
156 | |
157 | mutex_lock(&of_dma_lock); |
158 | |
159 | list_for_each_entry(ofdma, &of_dma_list, of_dma_controllers) |
160 | if (ofdma->of_node == np) { |
161 | list_del(entry: &ofdma->of_dma_controllers); |
162 | kfree(objp: ofdma); |
163 | break; |
164 | } |
165 | |
166 | mutex_unlock(lock: &of_dma_lock); |
167 | } |
168 | EXPORT_SYMBOL_GPL(of_dma_controller_free); |
169 | |
170 | /** |
171 | * of_dma_router_register - Register a DMA router to DT DMA helpers as a |
172 | * controller |
173 | * @np: device node of DMA router |
174 | * @of_dma_route_allocate: setup function for the router which need to |
175 | * modify the dma_spec for the DMA controller to |
176 | * use and to set up the requested route. |
177 | * @dma_router: pointer to dma_router structure to be used when |
178 | * the route need to be free up. |
179 | * |
180 | * Returns 0 on success or appropriate errno value on error. |
181 | * |
182 | * Allocated memory should be freed with appropriate of_dma_controller_free() |
183 | * call. |
184 | */ |
185 | int of_dma_router_register(struct device_node *np, |
186 | void *(*of_dma_route_allocate) |
187 | (struct of_phandle_args *, struct of_dma *), |
188 | struct dma_router *dma_router) |
189 | { |
190 | struct of_dma *ofdma; |
191 | |
192 | if (!np || !of_dma_route_allocate || !dma_router) { |
193 | pr_err("%s: not enough information provided\n" , __func__); |
194 | return -EINVAL; |
195 | } |
196 | |
197 | ofdma = kzalloc(size: sizeof(*ofdma), GFP_KERNEL); |
198 | if (!ofdma) |
199 | return -ENOMEM; |
200 | |
201 | ofdma->of_node = np; |
202 | ofdma->of_dma_xlate = of_dma_router_xlate; |
203 | ofdma->of_dma_route_allocate = of_dma_route_allocate; |
204 | ofdma->dma_router = dma_router; |
205 | |
206 | /* Now queue of_dma controller structure in list */ |
207 | mutex_lock(&of_dma_lock); |
208 | list_add_tail(new: &ofdma->of_dma_controllers, head: &of_dma_list); |
209 | mutex_unlock(lock: &of_dma_lock); |
210 | |
211 | return 0; |
212 | } |
213 | EXPORT_SYMBOL_GPL(of_dma_router_register); |
214 | |
215 | /** |
216 | * of_dma_match_channel - Check if a DMA specifier matches name |
217 | * @np: device node to look for DMA channels |
218 | * @name: channel name to be matched |
219 | * @index: index of DMA specifier in list of DMA specifiers |
220 | * @dma_spec: pointer to DMA specifier as found in the device tree |
221 | * |
222 | * Check if the DMA specifier pointed to by the index in a list of DMA |
223 | * specifiers, matches the name provided. Returns 0 if the name matches and |
224 | * a valid pointer to the DMA specifier is found. Otherwise returns -ENODEV. |
225 | */ |
226 | static int of_dma_match_channel(struct device_node *np, const char *name, |
227 | int index, struct of_phandle_args *dma_spec) |
228 | { |
229 | const char *s; |
230 | |
231 | if (of_property_read_string_index(np, propname: "dma-names" , index, output: &s)) |
232 | return -ENODEV; |
233 | |
234 | if (strcmp(name, s)) |
235 | return -ENODEV; |
236 | |
237 | if (of_parse_phandle_with_args(np, list_name: "dmas" , cells_name: "#dma-cells" , index, |
238 | out_args: dma_spec)) |
239 | return -ENODEV; |
240 | |
241 | return 0; |
242 | } |
243 | |
244 | /** |
245 | * of_dma_request_slave_channel - Get the DMA slave channel |
246 | * @np: device node to get DMA request from |
247 | * @name: name of desired channel |
248 | * |
249 | * Returns pointer to appropriate DMA channel on success or an error pointer. |
250 | */ |
251 | struct dma_chan *of_dma_request_slave_channel(struct device_node *np, |
252 | const char *name) |
253 | { |
254 | struct of_phandle_args dma_spec; |
255 | struct of_dma *ofdma; |
256 | struct dma_chan *chan; |
257 | int count, i, start; |
258 | int ret_no_channel = -ENODEV; |
259 | static atomic_t last_index; |
260 | |
261 | if (!np || !name) { |
262 | pr_err("%s: not enough information provided\n" , __func__); |
263 | return ERR_PTR(error: -ENODEV); |
264 | } |
265 | |
266 | /* Silently fail if there is not even the "dmas" property */ |
267 | if (!of_property_present(np, propname: "dmas" )) |
268 | return ERR_PTR(error: -ENODEV); |
269 | |
270 | count = of_property_count_strings(np, propname: "dma-names" ); |
271 | if (count < 0) { |
272 | pr_err("%s: dma-names property of node '%pOF' missing or empty\n" , |
273 | __func__, np); |
274 | return ERR_PTR(error: -ENODEV); |
275 | } |
276 | |
277 | /* |
278 | * approximate an average distribution across multiple |
279 | * entries with the same name |
280 | */ |
281 | start = atomic_inc_return(v: &last_index); |
282 | for (i = 0; i < count; i++) { |
283 | if (of_dma_match_channel(np, name, |
284 | index: (i + start) % count, |
285 | dma_spec: &dma_spec)) |
286 | continue; |
287 | |
288 | mutex_lock(&of_dma_lock); |
289 | ofdma = of_dma_find_controller(dma_spec: &dma_spec); |
290 | |
291 | if (ofdma) { |
292 | chan = ofdma->of_dma_xlate(&dma_spec, ofdma); |
293 | } else { |
294 | ret_no_channel = -EPROBE_DEFER; |
295 | chan = NULL; |
296 | } |
297 | |
298 | mutex_unlock(lock: &of_dma_lock); |
299 | |
300 | of_node_put(node: dma_spec.np); |
301 | |
302 | if (chan) |
303 | return chan; |
304 | } |
305 | |
306 | return ERR_PTR(error: ret_no_channel); |
307 | } |
308 | EXPORT_SYMBOL_GPL(of_dma_request_slave_channel); |
309 | |
310 | /** |
311 | * of_dma_simple_xlate - Simple DMA engine translation function |
312 | * @dma_spec: pointer to DMA specifier as found in the device tree |
313 | * @ofdma: pointer to DMA controller data |
314 | * |
315 | * A simple translation function for devices that use a 32-bit value for the |
316 | * filter_param when calling the DMA engine dma_request_channel() function. |
317 | * Note that this translation function requires that #dma-cells is equal to 1 |
318 | * and the argument of the dma specifier is the 32-bit filter_param. Returns |
319 | * pointer to appropriate dma channel on success or NULL on error. |
320 | */ |
321 | struct dma_chan *of_dma_simple_xlate(struct of_phandle_args *dma_spec, |
322 | struct of_dma *ofdma) |
323 | { |
324 | int count = dma_spec->args_count; |
325 | struct of_dma_filter_info *info = ofdma->of_dma_data; |
326 | |
327 | if (!info || !info->filter_fn) |
328 | return NULL; |
329 | |
330 | if (count != 1) |
331 | return NULL; |
332 | |
333 | return __dma_request_channel(mask: &info->dma_cap, fn: info->filter_fn, |
334 | fn_param: &dma_spec->args[0], np: dma_spec->np); |
335 | } |
336 | EXPORT_SYMBOL_GPL(of_dma_simple_xlate); |
337 | |
338 | /** |
339 | * of_dma_xlate_by_chan_id - Translate dt property to DMA channel by channel id |
340 | * @dma_spec: pointer to DMA specifier as found in the device tree |
341 | * @ofdma: pointer to DMA controller data |
342 | * |
343 | * This function can be used as the of xlate callback for DMA driver which wants |
344 | * to match the channel based on the channel id. When using this xlate function |
345 | * the #dma-cells propety of the DMA controller dt node needs to be set to 1. |
346 | * The data parameter of of_dma_controller_register must be a pointer to the |
347 | * dma_device struct the function should match upon. |
348 | * |
349 | * Returns pointer to appropriate dma channel on success or NULL on error. |
350 | */ |
351 | struct dma_chan *of_dma_xlate_by_chan_id(struct of_phandle_args *dma_spec, |
352 | struct of_dma *ofdma) |
353 | { |
354 | struct dma_device *dev = ofdma->of_dma_data; |
355 | struct dma_chan *chan, *candidate = NULL; |
356 | |
357 | if (!dev || dma_spec->args_count != 1) |
358 | return NULL; |
359 | |
360 | list_for_each_entry(chan, &dev->channels, device_node) |
361 | if (chan->chan_id == dma_spec->args[0]) { |
362 | candidate = chan; |
363 | break; |
364 | } |
365 | |
366 | if (!candidate) |
367 | return NULL; |
368 | |
369 | return dma_get_slave_channel(chan: candidate); |
370 | } |
371 | EXPORT_SYMBOL_GPL(of_dma_xlate_by_chan_id); |
372 | |