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