aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/acpi/enumeration.txt77
-rw-r--r--drivers/dma/Kconfig4
-rw-r--r--drivers/dma/Makefile1
-rw-r--r--drivers/dma/acpi-dma.c279
-rw-r--r--include/linux/acpi_dma.h116
5 files changed, 477 insertions, 0 deletions
diff --git a/Documentation/acpi/enumeration.txt b/Documentation/acpi/enumeration.txt
index 94a656131885..2874c904f3ef 100644
--- a/Documentation/acpi/enumeration.txt
+++ b/Documentation/acpi/enumeration.txt
@@ -66,6 +66,83 @@ the ACPI device explicitly to acpi_platform_device_ids list defined in
66drivers/acpi/acpi_platform.c. This limitation is only for the platform 66drivers/acpi/acpi_platform.c. This limitation is only for the platform
67devices, SPI and I2C devices are created automatically as described below. 67devices, SPI and I2C devices are created automatically as described below.
68 68
69DMA support
70~~~~~~~~~~~
71DMA controllers enumerated via ACPI should be registered in the system to
72provide generic access to their resources. For example, a driver that would
73like to be accessible to slave devices via generic API call
74dma_request_slave_channel() must register itself at the end of the probe
75function like this:
76
77 err = devm_acpi_dma_controller_register(dev, xlate_func, dw);
78 /* Handle the error if it's not a case of !CONFIG_ACPI */
79
80and implement custom xlate function if needed (usually acpi_dma_simple_xlate()
81is enough) which converts the FixedDMA resource provided by struct
82acpi_dma_spec into the corresponding DMA channel. A piece of code for that case
83could look like:
84
85 #ifdef CONFIG_ACPI
86 struct filter_args {
87 /* Provide necessary information for the filter_func */
88 ...
89 };
90
91 static bool filter_func(struct dma_chan *chan, void *param)
92 {
93 /* Choose the proper channel */
94 ...
95 }
96
97 static struct dma_chan *xlate_func(struct acpi_dma_spec *dma_spec,
98 struct acpi_dma *adma)
99 {
100 dma_cap_mask_t cap;
101 struct filter_args args;
102
103 /* Prepare arguments for filter_func */
104 ...
105 return dma_request_channel(cap, filter_func, &args);
106 }
107 #else
108 static struct dma_chan *xlate_func(struct acpi_dma_spec *dma_spec,
109 struct acpi_dma *adma)
110 {
111 return NULL;
112 }
113 #endif
114
115dma_request_slave_channel() will call xlate_func() for each registered DMA
116controller. In the xlate function the proper channel must be chosen based on
117information in struct acpi_dma_spec and the properties of the controller
118provided by struct acpi_dma.
119
120Clients must call dma_request_slave_channel() with the string parameter that
121corresponds to a specific FixedDMA resource. By default "tx" means the first
122entry of the FixedDMA resource array, "rx" means the second entry. The table
123below shows a layout:
124
125 Device (I2C0)
126 {
127 ...
128 Method (_CRS, 0, NotSerialized)
129 {
130 Name (DBUF, ResourceTemplate ()
131 {
132 FixedDMA (0x0018, 0x0004, Width32bit, _Y48)
133 FixedDMA (0x0019, 0x0005, Width32bit, )
134 })
135 ...
136 }
137 }
138
139So, the FixedDMA with request line 0x0018 is "tx" and next one is "rx" in
140this example.
141
142In robust cases the client unfortunately needs to call
143acpi_dma_request_slave_chan_by_index() directly and therefore choose the
144specific FixedDMA resource by its index.
145
69SPI serial bus support 146SPI serial bus support
70~~~~~~~~~~~~~~~~~~~~~~ 147~~~~~~~~~~~~~~~~~~~~~~
71Slave devices behind SPI bus have SpiSerialBus resource attached to them. 148Slave devices behind SPI bus have SpiSerialBus resource attached to them.
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index d5c58e839b27..afe5b1958382 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -326,6 +326,10 @@ config DMA_ENGINE
326config DMA_VIRTUAL_CHANNELS 326config DMA_VIRTUAL_CHANNELS
327 tristate 327 tristate
328 328
329config DMA_ACPI
330 def_bool y
331 depends on ACPI
332
329config DMA_OF 333config DMA_OF
330 def_bool y 334 def_bool y
331 depends on OF 335 depends on OF
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index 488e3ff85b52..268e62634bca 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -3,6 +3,7 @@ ccflags-$(CONFIG_DMADEVICES_VDEBUG) += -DVERBOSE_DEBUG
3 3
4obj-$(CONFIG_DMA_ENGINE) += dmaengine.o 4obj-$(CONFIG_DMA_ENGINE) += dmaengine.o
5obj-$(CONFIG_DMA_VIRTUAL_CHANNELS) += virt-dma.o 5obj-$(CONFIG_DMA_VIRTUAL_CHANNELS) += virt-dma.o
6obj-$(CONFIG_DMA_ACPI) += acpi-dma.o
6obj-$(CONFIG_DMA_OF) += of-dma.o 7obj-$(CONFIG_DMA_OF) += of-dma.o
7 8
8obj-$(CONFIG_NET_DMA) += iovlock.o 9obj-$(CONFIG_NET_DMA) += iovlock.o
diff --git a/drivers/dma/acpi-dma.c b/drivers/dma/acpi-dma.c
new file mode 100644
index 000000000000..ba6fc62e9651
--- /dev/null
+++ b/drivers/dma/acpi-dma.c
@@ -0,0 +1,279 @@
1/*
2 * ACPI helpers for DMA request / controller
3 *
4 * Based on of-dma.c
5 *
6 * Copyright (C) 2013, Intel Corporation
7 * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/device.h>
15#include <linux/module.h>
16#include <linux/list.h>
17#include <linux/mutex.h>
18#include <linux/slab.h>
19#include <linux/acpi.h>
20#include <linux/acpi_dma.h>
21
22static LIST_HEAD(acpi_dma_list);
23static DEFINE_MUTEX(acpi_dma_lock);
24
25/**
26 * acpi_dma_controller_register - Register a DMA controller to ACPI DMA helpers
27 * @dev: struct device of DMA controller
28 * @acpi_dma_xlate: translation function which converts a dma specifier
29 * into a dma_chan structure
30 * @data pointer to controller specific data to be used by
31 * translation function
32 *
33 * Returns 0 on success or appropriate errno value on error.
34 *
35 * Allocated memory should be freed with appropriate acpi_dma_controller_free()
36 * call.
37 */
38int acpi_dma_controller_register(struct device *dev,
39 struct dma_chan *(*acpi_dma_xlate)
40 (struct acpi_dma_spec *, struct acpi_dma *),
41 void *data)
42{
43 struct acpi_device *adev;
44 struct acpi_dma *adma;
45
46 if (!dev || !acpi_dma_xlate)
47 return -EINVAL;
48
49 /* Check if the device was enumerated by ACPI */
50 if (!ACPI_HANDLE(dev))
51 return -EINVAL;
52
53 if (acpi_bus_get_device(ACPI_HANDLE(dev), &adev))
54 return -EINVAL;
55
56 adma = kzalloc(sizeof(*adma), GFP_KERNEL);
57 if (!adma)
58 return -ENOMEM;
59
60 adma->dev = dev;
61 adma->acpi_dma_xlate = acpi_dma_xlate;
62 adma->data = data;
63
64 /* Now queue acpi_dma controller structure in list */
65 mutex_lock(&acpi_dma_lock);
66 list_add_tail(&adma->dma_controllers, &acpi_dma_list);
67 mutex_unlock(&acpi_dma_lock);
68
69 return 0;
70}
71EXPORT_SYMBOL_GPL(acpi_dma_controller_register);
72
73/**
74 * acpi_dma_controller_free - Remove a DMA controller from ACPI DMA helpers list
75 * @dev: struct device of DMA controller
76 *
77 * Memory allocated by acpi_dma_controller_register() is freed here.
78 */
79int acpi_dma_controller_free(struct device *de