Blame view

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

36bf8fc42   Andy Shevchenko   dmaengine: acpi-d...
450
451
  	dev_dbg(dev, "Looking for DMA channel \"%s\" at index %d...
  ", name, index);
1b2e98bc1   Andy Shevchenko   dma: acpi-dma: in...
452
453
454
455
456
457
458
459
460
461
  	return acpi_dma_request_slave_chan_by_index(dev, index);
  }
  EXPORT_SYMBOL_GPL(acpi_dma_request_slave_chan_by_name);
  
  /**
   * acpi_dma_simple_xlate - Simple ACPI DMA engine translation helper
   * @dma_spec: pointer to ACPI DMA specifier
   * @adma: pointer to ACPI DMA controller data
   *
   * A simple translation function for ACPI based devices. Passes &struct
39d144781   Andy Shevchenko   acpi-dma: align d...
462
463
464
465
   * dma_spec to the DMA controller driver provided filter function.
   *
   * Return:
   * Pointer to the channel if found or %NULL otherwise.
1b2e98bc1   Andy Shevchenko   dma: acpi-dma: in...
466
467
468
469
470
471
472
473
474
475
476
477
   */
  struct dma_chan *acpi_dma_simple_xlate(struct acpi_dma_spec *dma_spec,
  		struct acpi_dma *adma)
  {
  	struct acpi_dma_filter_info *info = adma->data;
  
  	if (!info || !info->filter_fn)
  		return NULL;
  
  	return dma_request_channel(info->dma_cap, info->filter_fn, dma_spec);
  }
  EXPORT_SYMBOL_GPL(acpi_dma_simple_xlate);