Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-only
2 : : /*
3 : : * ACPI helpers for DMA request / controller
4 : : *
5 : : * Based on of-dma.c
6 : : *
7 : : * Copyright (C) 2013, Intel Corporation
8 : : * Authors: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
9 : : * Mika Westerberg <mika.westerberg@linux.intel.com>
10 : : */
11 : :
12 : : #include <linux/device.h>
13 : : #include <linux/dma-mapping.h>
14 : : #include <linux/err.h>
15 : : #include <linux/module.h>
16 : : #include <linux/kernel.h>
17 : : #include <linux/list.h>
18 : : #include <linux/mutex.h>
19 : : #include <linux/slab.h>
20 : : #include <linux/ioport.h>
21 : : #include <linux/acpi.h>
22 : : #include <linux/acpi_dma.h>
23 : : #include <linux/property.h>
24 : :
25 : : static LIST_HEAD(acpi_dma_list);
26 : : static DEFINE_MUTEX(acpi_dma_lock);
27 : :
28 : : /**
29 : : * acpi_dma_parse_resource_group - match device and parse resource group
30 : : * @grp: CSRT resource group
31 : : * @adev: ACPI device to match with
32 : : * @adma: struct acpi_dma of the given DMA controller
33 : : *
34 : : * In order to match a device from DSDT table to the corresponding CSRT device
35 : : * we use MMIO address and IRQ.
36 : : *
37 : : * Return:
38 : : * 1 on success, 0 when no information is available, or appropriate errno value
39 : : * on error.
40 : : */
41 : : static int acpi_dma_parse_resource_group(const struct acpi_csrt_group *grp,
42 : : struct acpi_device *adev, struct acpi_dma *adma)
43 : : {
44 : : const struct acpi_csrt_shared_info *si;
45 : : struct list_head resource_list;
46 : : struct resource_entry *rentry;
47 : : resource_size_t mem = 0, irq = 0;
48 : : int ret;
49 : :
50 : : if (grp->shared_info_length != sizeof(struct acpi_csrt_shared_info))
51 : : return -ENODEV;
52 : :
53 : : INIT_LIST_HEAD(&resource_list);
54 : : ret = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
55 : : if (ret <= 0)
56 : : return 0;
57 : :
58 : : list_for_each_entry(rentry, &resource_list, node) {
59 : : if (resource_type(rentry->res) == IORESOURCE_MEM)
60 : : mem = rentry->res->start;
61 : : else if (resource_type(rentry->res) == IORESOURCE_IRQ)
62 : : irq = rentry->res->start;
63 : : }
64 : :
65 : : acpi_dev_free_resource_list(&resource_list);
66 : :
67 : : /* Consider initial zero values as resource not found */
68 : : if (mem == 0 && irq == 0)
69 : : return 0;
70 : :
71 : : si = (const struct acpi_csrt_shared_info *)&grp[1];
72 : :
73 : : /* Match device by MMIO and IRQ */
74 : : if (si->mmio_base_low != lower_32_bits(mem) ||
75 : : si->mmio_base_high != upper_32_bits(mem) ||
76 : : si->gsi_interrupt != irq)
77 : : return 0;
78 : :
79 : : dev_dbg(&adev->dev, "matches with %.4s%04X (rev %u)\n",
80 : : (char *)&grp->vendor_id, grp->device_id, grp->revision);
81 : :
82 : : /* Check if the request line range is available */
83 : : if (si->base_request_line == 0 && si->num_handshake_signals == 0)
84 : : return 0;
85 : :
86 : : /* Set up DMA mask based on value from CSRT */
87 : : ret = dma_coerce_mask_and_coherent(&adev->dev,
88 : : DMA_BIT_MASK(si->dma_address_width));
89 : : if (ret)
90 : : return 0;
91 : :
92 : : adma->base_request_line = si->base_request_line;
93 : : adma->end_request_line = si->base_request_line +
94 : : si->num_handshake_signals - 1;
95 : :
96 : : dev_dbg(&adev->dev, "request line base: 0x%04x end: 0x%04x\n",
97 : : adma->base_request_line, adma->end_request_line);
98 : :
99 : : return 1;
100 : : }
101 : :
102 : : /**
103 : : * acpi_dma_parse_csrt - parse CSRT to exctract additional DMA resources
104 : : * @adev: ACPI device to match with
105 : : * @adma: struct acpi_dma of the given DMA controller
106 : : *
107 : : * CSRT or Core System Resources Table is a proprietary ACPI table
108 : : * introduced by Microsoft. This table can contain devices that are not in
109 : : * the system DSDT table. In particular DMA controllers might be described
110 : : * here.
111 : : *
112 : : * We are using this table to get the request line range of the specific DMA
113 : : * controller to be used later.
114 : : */
115 : 0 : static void acpi_dma_parse_csrt(struct acpi_device *adev, struct acpi_dma *adma)
116 : : {
117 : 0 : struct acpi_csrt_group *grp, *end;
118 : 0 : struct acpi_table_csrt *csrt;
119 : 0 : acpi_status status;
120 : 0 : int ret;
121 : :
122 : 0 : status = acpi_get_table(ACPI_SIG_CSRT, 0,
123 : : (struct acpi_table_header **)&csrt);
124 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
125 [ # # ]: 0 : if (status != AE_NOT_FOUND)
126 : 0 : dev_warn(&adev->dev, "failed to get the CSRT table\n");
127 : 0 : return;
128 : : }
129 : :
130 : 0 : grp = (struct acpi_csrt_group *)(csrt + 1);
131 : 0 : end = (struct acpi_csrt_group *)((void *)csrt + csrt->header.length);
132 : :
133 [ # # ]: 0 : while (grp < end) {
134 : 0 : ret = acpi_dma_parse_resource_group(grp, adev, adma);
135 [ # # ]: 0 : if (ret < 0) {
136 : 0 : dev_warn(&adev->dev,
137 : : "error in parsing resource group\n");
138 : 0 : return;
139 : : }
140 : :
141 : 0 : grp = (struct acpi_csrt_group *)((void *)grp + grp->length);
142 : : }
143 : : }
144 : :
145 : : /**
146 : : * acpi_dma_controller_register - Register a DMA controller to ACPI DMA helpers
147 : : * @dev: struct device of DMA controller
148 : : * @acpi_dma_xlate: translation function which converts a dma specifier
149 : : * into a dma_chan structure
150 : : * @data: pointer to controller specific data to be used by
151 : : * translation function
152 : : *
153 : : * Allocated memory should be freed with appropriate acpi_dma_controller_free()
154 : : * call.
155 : : *
156 : : * Return:
157 : : * 0 on success or appropriate errno value on error.
158 : : */
159 : 0 : int acpi_dma_controller_register(struct device *dev,
160 : : struct dma_chan *(*acpi_dma_xlate)
161 : : (struct acpi_dma_spec *, struct acpi_dma *),
162 : : void *data)
163 : : {
164 : 0 : struct acpi_device *adev;
165 : 0 : struct acpi_dma *adma;
166 : :
167 [ # # ]: 0 : if (!dev || !acpi_dma_xlate)
168 : : return -EINVAL;
169 : :
170 : : /* Check if the device was enumerated by ACPI */
171 [ # # ]: 0 : adev = ACPI_COMPANION(dev);
172 [ # # ]: 0 : if (!adev)
173 : : return -EINVAL;
174 : :
175 : 0 : adma = kzalloc(sizeof(*adma), GFP_KERNEL);
176 [ # # ]: 0 : if (!adma)
177 : : return -ENOMEM;
178 : :
179 : 0 : adma->dev = dev;
180 : 0 : adma->acpi_dma_xlate = acpi_dma_xlate;
181 : 0 : adma->data = data;
182 : :
183 : 0 : acpi_dma_parse_csrt(adev, adma);
184 : :
185 : : /* Now queue acpi_dma controller structure in list */
186 : 0 : mutex_lock(&acpi_dma_lock);
187 : 0 : list_add_tail(&adma->dma_controllers, &acpi_dma_list);
188 : 0 : mutex_unlock(&acpi_dma_lock);
189 : :
190 : 0 : return 0;
191 : : }
192 : : EXPORT_SYMBOL_GPL(acpi_dma_controller_register);
193 : :
194 : : /**
195 : : * acpi_dma_controller_free - Remove a DMA controller from ACPI DMA helpers list
196 : : * @dev: struct device of DMA controller
197 : : *
198 : : * Memory allocated by acpi_dma_controller_register() is freed here.
199 : : *
200 : : * Return:
201 : : * 0 on success or appropriate errno value on error.
202 : : */
203 : 0 : int acpi_dma_controller_free(struct device *dev)
204 : : {
205 : 0 : struct acpi_dma *adma;
206 : :
207 [ # # ]: 0 : if (!dev)
208 : : return -EINVAL;
209 : :
210 : 0 : mutex_lock(&acpi_dma_lock);
211 : :
212 [ # # ]: 0 : list_for_each_entry(adma, &acpi_dma_list, dma_controllers)
213 [ # # ]: 0 : if (adma->dev == dev) {
214 : 0 : list_del(&adma->dma_controllers);
215 : 0 : mutex_unlock(&acpi_dma_lock);
216 : 0 : kfree(adma);
217 : 0 : return 0;
218 : : }
219 : :
220 : 0 : mutex_unlock(&acpi_dma_lock);
221 : 0 : return -ENODEV;
222 : : }
223 : : EXPORT_SYMBOL_GPL(acpi_dma_controller_free);
224 : :
225 : 0 : static void devm_acpi_dma_release(struct device *dev, void *res)
226 : : {
227 : 0 : acpi_dma_controller_free(dev);
228 : 0 : }
229 : :
230 : : /**
231 : : * devm_acpi_dma_controller_register - resource managed acpi_dma_controller_register()
232 : : * @dev: device that is registering this DMA controller
233 : : * @acpi_dma_xlate: translation function
234 : : * @data: pointer to controller specific data
235 : : *
236 : : * Managed acpi_dma_controller_register(). DMA controller registered by this
237 : : * function are automatically freed on driver detach. See
238 : : * acpi_dma_controller_register() for more information.
239 : : *
240 : : * Return:
241 : : * 0 on success or appropriate errno value on error.
242 : : */
243 : 0 : int devm_acpi_dma_controller_register(struct device *dev,
244 : : struct dma_chan *(*acpi_dma_xlate)
245 : : (struct acpi_dma_spec *, struct acpi_dma *),
246 : : void *data)
247 : : {
248 : 0 : void *res;
249 : 0 : int ret;
250 : :
251 : 0 : res = devres_alloc(devm_acpi_dma_release, 0, GFP_KERNEL);
252 [ # # ]: 0 : if (!res)
253 : : return -ENOMEM;
254 : :
255 : 0 : ret = acpi_dma_controller_register(dev, acpi_dma_xlate, data);
256 [ # # ]: 0 : if (ret) {
257 : 0 : devres_free(res);
258 : 0 : return ret;
259 : : }
260 : 0 : devres_add(dev, res);
261 : 0 : return 0;
262 : : }
263 : : EXPORT_SYMBOL_GPL(devm_acpi_dma_controller_register);
264 : :
265 : : /**
266 : : * devm_acpi_dma_controller_free - resource managed acpi_dma_controller_free()
267 : : * @dev: device that is unregistering as DMA controller
268 : : *
269 : : * Unregister a DMA controller registered with
270 : : * devm_acpi_dma_controller_register(). Normally this function will not need to
271 : : * be called and the resource management code will ensure that the resource is
272 : : * freed.
273 : : */
274 : 0 : void devm_acpi_dma_controller_free(struct device *dev)
275 : : {
276 [ # # ]: 0 : WARN_ON(devres_release(dev, devm_acpi_dma_release, NULL, NULL));
277 : 0 : }
278 : : EXPORT_SYMBOL_GPL(devm_acpi_dma_controller_free);
279 : :
280 : : /**
281 : : * acpi_dma_update_dma_spec - prepare dma specifier to pass to translation function
282 : : * @adma: struct acpi_dma of DMA controller
283 : : * @dma_spec: dma specifier to update
284 : : *
285 : : * Accordingly to ACPI 5.0 Specification Table 6-170 "Fixed DMA Resource
286 : : * Descriptor":
287 : : * DMA Request Line bits is a platform-relative number uniquely
288 : : * identifying the request line assigned. Request line-to-Controller
289 : : * mapping is done in a controller-specific OS driver.
290 : : * That's why we can safely adjust slave_id when the appropriate controller is
291 : : * found.
292 : : *
293 : : * Return:
294 : : * 0, if no information is avaiable, -1 on mismatch, and 1 otherwise.
295 : : */
296 : 0 : static int acpi_dma_update_dma_spec(struct acpi_dma *adma,
297 : : struct acpi_dma_spec *dma_spec)
298 : : {
299 : : /* Set link to the DMA controller device */
300 : 0 : dma_spec->dev = adma->dev;
301 : :
302 : : /* Check if the request line range is available */
303 : 0 : if (adma->base_request_line == 0 && adma->end_request_line == 0)
304 : : return 0;
305 : :
306 : : /* Check if slave_id falls to the range */
307 [ # # ]: 0 : if (dma_spec->slave_id < adma->base_request_line ||
308 [ # # ]: 0 : dma_spec->slave_id > adma->end_request_line)
309 : : return -1;
310 : :
311 : : /*
312 : : * Here we adjust slave_id. It should be a relative number to the base
313 : : * request line.
314 : : */
315 : 0 : dma_spec->slave_id -= adma->base_request_line;
316 : :
317 : 0 : return 1;
318 : : }
319 : :
320 : : struct acpi_dma_parser_data {
321 : : struct acpi_dma_spec dma_spec;
322 : : size_t index;
323 : : size_t n;
324 : : };
325 : :
326 : : /**
327 : : * acpi_dma_parse_fixed_dma - Parse FixedDMA ACPI resources to a DMA specifier
328 : : * @res: struct acpi_resource to get FixedDMA resources from
329 : : * @data: pointer to a helper struct acpi_dma_parser_data
330 : : */
331 : 0 : static int acpi_dma_parse_fixed_dma(struct acpi_resource *res, void *data)
332 : : {
333 : 0 : struct acpi_dma_parser_data *pdata = data;
334 : :
335 [ # # ]: 0 : if (res->type == ACPI_RESOURCE_TYPE_FIXED_DMA) {
336 : 0 : struct acpi_resource_fixed_dma *dma = &res->data.fixed_dma;
337 : :
338 [ # # ]: 0 : if (pdata->n++ == pdata->index) {
339 : 0 : pdata->dma_spec.chan_id = dma->channels;
340 : 0 : pdata->dma_spec.slave_id = dma->request_lines;
341 : : }
342 : : }
343 : :
344 : : /* Tell the ACPI core to skip this resource */
345 : 0 : return 1;
346 : : }
347 : :
348 : : /**
349 : : * acpi_dma_request_slave_chan_by_index - Get the DMA slave channel
350 : : * @dev: struct device to get DMA request from
351 : : * @index: index of FixedDMA descriptor for @dev
352 : : *
353 : : * Return:
354 : : * Pointer to appropriate dma channel on success or an error pointer.
355 : : */
356 : 0 : struct dma_chan *acpi_dma_request_slave_chan_by_index(struct device *dev,
357 : : size_t index)
358 : : {
359 : 0 : struct acpi_dma_parser_data pdata;
360 : 0 : struct acpi_dma_spec *dma_spec = &pdata.dma_spec;
361 : 0 : struct list_head resource_list;
362 : 0 : struct acpi_device *adev;
363 : 0 : struct acpi_dma *adma;
364 : 0 : struct dma_chan *chan = NULL;
365 : 0 : int found;
366 : :
367 : : /* Check if the device was enumerated by ACPI */
368 [ # # ]: 0 : if (!dev)
369 : : return ERR_PTR(-ENODEV);
370 : :
371 [ # # ]: 0 : adev = ACPI_COMPANION(dev);
372 [ # # ]: 0 : if (!adev)
373 : : return ERR_PTR(-ENODEV);
374 : :
375 : 0 : memset(&pdata, 0, sizeof(pdata));
376 : 0 : pdata.index = index;
377 : :
378 : : /* Initial values for the request line and channel */
379 : 0 : dma_spec->chan_id = -1;
380 : 0 : dma_spec->slave_id = -1;
381 : :
382 : 0 : INIT_LIST_HEAD(&resource_list);
383 : 0 : acpi_dev_get_resources(adev, &resource_list,
384 : : acpi_dma_parse_fixed_dma, &pdata);
385 : 0 : acpi_dev_free_resource_list(&resource_list);
386 : :
387 [ # # # # ]: 0 : if (dma_spec->slave_id < 0 || dma_spec->chan_id < 0)
388 : : return ERR_PTR(-ENODEV);
389 : :
390 : 0 : mutex_lock(&acpi_dma_lock);
391 : :
392 [ # # ]: 0 : list_for_each_entry(adma, &acpi_dma_list, dma_controllers) {
393 : : /*
394 : : * We are not going to call translation function if slave_id
395 : : * doesn't fall to the request range.
396 : : */
397 [ # # ]: 0 : found = acpi_dma_update_dma_spec(adma, dma_spec);
398 : 0 : if (found < 0)
399 : 0 : continue;
400 : 0 : chan = adma->acpi_dma_xlate(dma_spec, adma);
401 : : /*
402 : : * Try to get a channel only from the DMA controller that
403 : : * matches the slave_id. See acpi_dma_update_dma_spec()
404 : : * description for the details.
405 : : */
406 [ # # ]: 0 : if (found > 0 || chan)
407 : : break;
408 : : }
409 : :
410 : 0 : mutex_unlock(&acpi_dma_lock);
411 [ # # ]: 0 : return chan ? chan : ERR_PTR(-EPROBE_DEFER);
412 : : }
413 : : EXPORT_SYMBOL_GPL(acpi_dma_request_slave_chan_by_index);
414 : :
415 : : /**
416 : : * acpi_dma_request_slave_chan_by_name - Get the DMA slave channel
417 : : * @dev: struct device to get DMA request from
418 : : * @name: represents corresponding FixedDMA descriptor for @dev
419 : : *
420 : : * In order to support both Device Tree and ACPI in a single driver we
421 : : * translate the names "tx" and "rx" here based on the most common case where
422 : : * the first FixedDMA descriptor is TX and second is RX.
423 : : *
424 : : * If the device has "dma-names" property the FixedDMA descriptor indices
425 : : * are retrieved based on those. Otherwise the function falls back using
426 : : * hardcoded indices.
427 : : *
428 : : * Return:
429 : : * Pointer to appropriate dma channel on success or an error pointer.
430 : : */
431 : 0 : struct dma_chan *acpi_dma_request_slave_chan_by_name(struct device *dev,
432 : : const char *name)
433 : : {
434 : 0 : int index;
435 : :
436 : 0 : index = device_property_match_string(dev, "dma-names", name);
437 [ # # ]: 0 : if (index < 0) {
438 [ # # ]: 0 : if (!strcmp(name, "tx"))
439 : : index = 0;
440 [ # # ]: 0 : else if (!strcmp(name, "rx"))
441 : : index = 1;
442 : : else
443 : : return ERR_PTR(-ENODEV);
444 : : }
445 : :
446 : 0 : dev_dbg(dev, "Looking for DMA channel \"%s\" at index %d...\n", name, index);
447 : 0 : return acpi_dma_request_slave_chan_by_index(dev, index);
448 : : }
449 : : EXPORT_SYMBOL_GPL(acpi_dma_request_slave_chan_by_name);
450 : :
451 : : /**
452 : : * acpi_dma_simple_xlate - Simple ACPI DMA engine translation helper
453 : : * @dma_spec: pointer to ACPI DMA specifier
454 : : * @adma: pointer to ACPI DMA controller data
455 : : *
456 : : * A simple translation function for ACPI based devices. Passes &struct
457 : : * dma_spec to the DMA controller driver provided filter function.
458 : : *
459 : : * Return:
460 : : * Pointer to the channel if found or %NULL otherwise.
461 : : */
462 : 0 : struct dma_chan *acpi_dma_simple_xlate(struct acpi_dma_spec *dma_spec,
463 : : struct acpi_dma *adma)
464 : : {
465 : 0 : struct acpi_dma_filter_info *info = adma->data;
466 : :
467 [ # # # # ]: 0 : if (!info || !info->filter_fn)
468 : : return NULL;
469 : :
470 : 0 : return dma_request_channel(info->dma_cap, info->filter_fn, dma_spec);
471 : : }
472 : : EXPORT_SYMBOL_GPL(acpi_dma_simple_xlate);
|