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