xref: /openbmc/linux/drivers/dma/acpi-dma.c (revision ca79522c)
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 
22 static LIST_HEAD(acpi_dma_list);
23 static 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  */
38 int 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 }
71 EXPORT_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  */
79 int acpi_dma_controller_free(struct device *dev)
80 {
81 	struct acpi_dma *adma;
82 
83 	if (!dev)
84 		return -EINVAL;
85 
86 	mutex_lock(&acpi_dma_lock);
87 
88 	list_for_each_entry(adma, &acpi_dma_list, dma_controllers)
89 		if (adma->dev == dev) {
90 			list_del(&adma->dma_controllers);
91 			mutex_unlock(&acpi_dma_lock);
92 			kfree(adma);
93 			return 0;
94 		}
95 
96 	mutex_unlock(&acpi_dma_lock);
97 	return -ENODEV;
98 }
99 EXPORT_SYMBOL_GPL(acpi_dma_controller_free);
100 
101 static void devm_acpi_dma_release(struct device *dev, void *res)
102 {
103 	acpi_dma_controller_free(dev);
104 }
105 
106 /**
107  * devm_acpi_dma_controller_register - resource managed acpi_dma_controller_register()
108  * @dev:		device that is registering this DMA controller
109  * @acpi_dma_xlate:	translation function
110  * @data		pointer to controller specific data
111  *
112  * Managed acpi_dma_controller_register(). DMA controller registered by this
113  * function are automatically freed on driver detach. See
114  * acpi_dma_controller_register() for more information.
115  */
116 int devm_acpi_dma_controller_register(struct device *dev,
117 		struct dma_chan *(*acpi_dma_xlate)
118 		(struct acpi_dma_spec *, struct acpi_dma *),
119 		void *data)
120 {
121 	void *res;
122 	int ret;
123 
124 	res = devres_alloc(devm_acpi_dma_release, 0, GFP_KERNEL);
125 	if (!res)
126 		return -ENOMEM;
127 
128 	ret = acpi_dma_controller_register(dev, acpi_dma_xlate, data);
129 	if (ret) {
130 		devres_free(res);
131 		return ret;
132 	}
133 	devres_add(dev, res);
134 	return 0;
135 }
136 EXPORT_SYMBOL_GPL(devm_acpi_dma_controller_register);
137 
138 /**
139  * devm_acpi_dma_controller_free - resource managed acpi_dma_controller_free()
140  *
141  * Unregister a DMA controller registered with
142  * devm_acpi_dma_controller_register(). Normally this function will not need to
143  * be called and the resource management code will ensure that the resource is
144  * freed.
145  */
146 void devm_acpi_dma_controller_free(struct device *dev)
147 {
148 	WARN_ON(devres_destroy(dev, devm_acpi_dma_release, NULL, NULL));
149 }
150 EXPORT_SYMBOL_GPL(devm_acpi_dma_controller_free);
151 
152 struct acpi_dma_parser_data {
153 	struct acpi_dma_spec dma_spec;
154 	size_t index;
155 	size_t n;
156 };
157 
158 /**
159  * acpi_dma_parse_fixed_dma - Parse FixedDMA ACPI resources to a DMA specifier
160  * @res:	struct acpi_resource to get FixedDMA resources from
161  * @data:	pointer to a helper struct acpi_dma_parser_data
162  */
163 static int acpi_dma_parse_fixed_dma(struct acpi_resource *res, void *data)
164 {
165 	struct acpi_dma_parser_data *pdata = data;
166 
167 	if (res->type == ACPI_RESOURCE_TYPE_FIXED_DMA) {
168 		struct acpi_resource_fixed_dma *dma = &res->data.fixed_dma;
169 
170 		if (pdata->n++ == pdata->index) {
171 			pdata->dma_spec.chan_id = dma->channels;
172 			pdata->dma_spec.slave_id = dma->request_lines;
173 		}
174 	}
175 
176 	/* Tell the ACPI core to skip this resource */
177 	return 1;
178 }
179 
180 /**
181  * acpi_dma_request_slave_chan_by_index - Get the DMA slave channel
182  * @dev:	struct device to get DMA request from
183  * @index:	index of FixedDMA descriptor for @dev
184  *
185  * Returns pointer to appropriate dma channel on success or NULL on error.
186  */
187 struct dma_chan *acpi_dma_request_slave_chan_by_index(struct device *dev,
188 		size_t index)
189 {
190 	struct acpi_dma_parser_data pdata;
191 	struct acpi_dma_spec *dma_spec = &pdata.dma_spec;
192 	struct list_head resource_list;
193 	struct acpi_device *adev;
194 	struct acpi_dma *adma;
195 	struct dma_chan *chan = NULL;
196 
197 	/* Check if the device was enumerated by ACPI */
198 	if (!dev || !ACPI_HANDLE(dev))
199 		return NULL;
200 
201 	if (acpi_bus_get_device(ACPI_HANDLE(dev), &adev))
202 		return NULL;
203 
204 	memset(&pdata, 0, sizeof(pdata));
205 	pdata.index = index;
206 
207 	/* Initial values for the request line and channel */
208 	dma_spec->chan_id = -1;
209 	dma_spec->slave_id = -1;
210 
211 	INIT_LIST_HEAD(&resource_list);
212 	acpi_dev_get_resources(adev, &resource_list,
213 			acpi_dma_parse_fixed_dma, &pdata);
214 	acpi_dev_free_resource_list(&resource_list);
215 
216 	if (dma_spec->slave_id < 0 || dma_spec->chan_id < 0)
217 		return NULL;
218 
219 	mutex_lock(&acpi_dma_lock);
220 
221 	list_for_each_entry(adma, &acpi_dma_list, dma_controllers) {
222 		dma_spec->dev = adma->dev;
223 		chan = adma->acpi_dma_xlate(dma_spec, adma);
224 		if (chan)
225 			break;
226 	}
227 
228 	mutex_unlock(&acpi_dma_lock);
229 	return chan;
230 }
231 EXPORT_SYMBOL_GPL(acpi_dma_request_slave_chan_by_index);
232 
233 /**
234  * acpi_dma_request_slave_chan_by_name - Get the DMA slave channel
235  * @dev:	struct device to get DMA request from
236  * @name:	represents corresponding FixedDMA descriptor for @dev
237  *
238  * In order to support both Device Tree and ACPI in a single driver we
239  * translate the names "tx" and "rx" here based on the most common case where
240  * the first FixedDMA descriptor is TX and second is RX.
241  *
242  * Returns pointer to appropriate dma channel on success or NULL on error.
243  */
244 struct dma_chan *acpi_dma_request_slave_chan_by_name(struct device *dev,
245 		const char *name)
246 {
247 	size_t index;
248 
249 	if (!strcmp(name, "tx"))
250 		index = 0;
251 	else if (!strcmp(name, "rx"))
252 		index = 1;
253 	else
254 		return NULL;
255 
256 	return acpi_dma_request_slave_chan_by_index(dev, index);
257 }
258 EXPORT_SYMBOL_GPL(acpi_dma_request_slave_chan_by_name);
259 
260 /**
261  * acpi_dma_simple_xlate - Simple ACPI DMA engine translation helper
262  * @dma_spec: pointer to ACPI DMA specifier
263  * @adma: pointer to ACPI DMA controller data
264  *
265  * A simple translation function for ACPI based devices. Passes &struct
266  * dma_spec to the DMA controller driver provided filter function. Returns
267  * pointer to the channel if found or %NULL otherwise.
268  */
269 struct dma_chan *acpi_dma_simple_xlate(struct acpi_dma_spec *dma_spec,
270 		struct acpi_dma *adma)
271 {
272 	struct acpi_dma_filter_info *info = adma->data;
273 
274 	if (!info || !info->filter_fn)
275 		return NULL;
276 
277 	return dma_request_channel(info->dma_cap, info->filter_fn, dma_spec);
278 }
279 EXPORT_SYMBOL_GPL(acpi_dma_simple_xlate);
280