11b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko/* 21b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * ACPI helpers for DMA request / controller 31b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * 41b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * Based on of-dma.c 51b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * 61b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * Copyright (C) 2013, Intel Corporation 7ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko * Authors: Andy Shevchenko <andriy.shevchenko@linux.intel.com> 8ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko * Mika Westerberg <mika.westerberg@linux.intel.com> 91b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * 101b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * This program is free software; you can redistribute it and/or modify 111b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * it under the terms of the GNU General Public License version 2 as 121b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * published by the Free Software Foundation. 131b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko */ 141b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko 151b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko#include <linux/device.h> 160f6a928d035b82c0b3aa387d510a73f3e6dbf8e3Andy Shevchenko#include <linux/err.h> 171b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko#include <linux/module.h> 181b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko#include <linux/list.h> 191b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko#include <linux/mutex.h> 201b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko#include <linux/slab.h> 21ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko#include <linux/ioport.h> 221b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko#include <linux/acpi.h> 231b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko#include <linux/acpi_dma.h> 241b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko 251b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenkostatic LIST_HEAD(acpi_dma_list); 261b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenkostatic DEFINE_MUTEX(acpi_dma_lock); 271b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko 281b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko/** 29ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko * acpi_dma_parse_resource_group - match device and parse resource group 30ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko * @grp: CSRT resource group 31ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko * @adev: ACPI device to match with 32ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko * @adma: struct acpi_dma of the given DMA controller 33ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko * 34ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko * In order to match a device from DSDT table to the corresponding CSRT device 35ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko * we use MMIO address and IRQ. 3639d1447811fef1262ba956aac719c90a0f7b257fAndy Shevchenko * 3739d1447811fef1262ba956aac719c90a0f7b257fAndy Shevchenko * Return: 3839d1447811fef1262ba956aac719c90a0f7b257fAndy Shevchenko * 1 on success, 0 when no information is available, or appropriate errno value 3939d1447811fef1262ba956aac719c90a0f7b257fAndy Shevchenko * on error. 40ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko */ 41ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenkostatic int acpi_dma_parse_resource_group(const struct acpi_csrt_group *grp, 42ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko struct acpi_device *adev, struct acpi_dma *adma) 43ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko{ 44ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko const struct acpi_csrt_shared_info *si; 45ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko struct list_head resource_list; 46ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko struct resource_list_entry *rentry; 47ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko resource_size_t mem = 0, irq = 0; 48ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko int ret; 49ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko 50ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko if (grp->shared_info_length != sizeof(struct acpi_csrt_shared_info)) 51ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko return -ENODEV; 52ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko 53ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko INIT_LIST_HEAD(&resource_list); 54ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko ret = acpi_dev_get_resources(adev, &resource_list, NULL, NULL); 55ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko if (ret <= 0) 56ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko return 0; 57ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko 58ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko list_for_each_entry(rentry, &resource_list, node) { 59ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko if (resource_type(&rentry->res) == IORESOURCE_MEM) 60ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko mem = rentry->res.start; 61ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko else if (resource_type(&rentry->res) == IORESOURCE_IRQ) 62ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko irq = rentry->res.start; 63ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko } 64ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko 65ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko acpi_dev_free_resource_list(&resource_list); 66ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko 67ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko /* Consider initial zero values as resource not found */ 68ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko if (mem == 0 && irq == 0) 69ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko return 0; 70ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko 71ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko si = (const struct acpi_csrt_shared_info *)&grp[1]; 72ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko 73ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko /* Match device by MMIO and IRQ */ 74ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko if (si->mmio_base_low != mem || si->gsi_interrupt != irq) 75ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko return 0; 76ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko 77ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko dev_dbg(&adev->dev, "matches with %.4s%04X (rev %u)\n", 78b4d6d336762aea282921a3283f2a00c7e95d2befAndy Shevchenko (char *)&grp->vendor_id, grp->device_id, grp->revision); 79ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko 80ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko /* Check if the request line range is available */ 81ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko if (si->base_request_line == 0 && si->num_handshake_signals == 0) 82ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko return 0; 83ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko 84ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko adma->base_request_line = si->base_request_line; 85ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko adma->end_request_line = si->base_request_line + 86ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko si->num_handshake_signals - 1; 87ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko 88ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko dev_dbg(&adev->dev, "request line base: 0x%04x end: 0x%04x\n", 89ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko adma->base_request_line, adma->end_request_line); 90ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko 91ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko return 1; 92ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko} 93ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko 94ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko/** 95ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko * acpi_dma_parse_csrt - parse CSRT to exctract additional DMA resources 96ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko * @adev: ACPI device to match with 97ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko * @adma: struct acpi_dma of the given DMA controller 98ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko * 99ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko * CSRT or Core System Resources Table is a proprietary ACPI table 100ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko * introduced by Microsoft. This table can contain devices that are not in 101ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko * the system DSDT table. In particular DMA controllers might be described 102ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko * here. 103ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko * 104ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko * We are using this table to get the request line range of the specific DMA 105ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko * controller to be used later. 106ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko */ 107ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenkostatic void acpi_dma_parse_csrt(struct acpi_device *adev, struct acpi_dma *adma) 108ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko{ 109ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko struct acpi_csrt_group *grp, *end; 110ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko struct acpi_table_csrt *csrt; 111ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko acpi_status status; 112ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko int ret; 113ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko 114ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko status = acpi_get_table(ACPI_SIG_CSRT, 0, 115ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko (struct acpi_table_header **)&csrt); 116ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko if (ACPI_FAILURE(status)) { 117ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko if (status != AE_NOT_FOUND) 118ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko dev_warn(&adev->dev, "failed to get the CSRT table\n"); 119ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko return; 120ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko } 121ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko 122ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko grp = (struct acpi_csrt_group *)(csrt + 1); 123ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko end = (struct acpi_csrt_group *)((void *)csrt + csrt->header.length); 124ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko 125ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko while (grp < end) { 126ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko ret = acpi_dma_parse_resource_group(grp, adev, adma); 127ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko if (ret < 0) { 128ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko dev_warn(&adev->dev, 129ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko "error in parsing resource group\n"); 130ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko return; 131ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko } 132ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko 133ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko grp = (struct acpi_csrt_group *)((void *)grp + grp->length); 134ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko } 135ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko} 136ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko 137ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko/** 1381b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * acpi_dma_controller_register - Register a DMA controller to ACPI DMA helpers 1391b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * @dev: struct device of DMA controller 1401b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * @acpi_dma_xlate: translation function which converts a dma specifier 1411b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * into a dma_chan structure 1421b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * @data pointer to controller specific data to be used by 1431b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * translation function 1441b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * 1451b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * Allocated memory should be freed with appropriate acpi_dma_controller_free() 1461b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * call. 14739d1447811fef1262ba956aac719c90a0f7b257fAndy Shevchenko * 14839d1447811fef1262ba956aac719c90a0f7b257fAndy Shevchenko * Return: 14939d1447811fef1262ba956aac719c90a0f7b257fAndy Shevchenko * 0 on success or appropriate errno value on error. 1501b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko */ 1511b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenkoint acpi_dma_controller_register(struct device *dev, 1521b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko struct dma_chan *(*acpi_dma_xlate) 1531b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko (struct acpi_dma_spec *, struct acpi_dma *), 1541b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko void *data) 1551b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko{ 1561b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko struct acpi_device *adev; 1571b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko struct acpi_dma *adma; 1581b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko 1591b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko if (!dev || !acpi_dma_xlate) 1601b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko return -EINVAL; 1611b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko 1621b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko /* Check if the device was enumerated by ACPI */ 1631b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko if (!ACPI_HANDLE(dev)) 1641b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko return -EINVAL; 1651b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko 1661b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko if (acpi_bus_get_device(ACPI_HANDLE(dev), &adev)) 1671b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko return -EINVAL; 1681b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko 1691b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko adma = kzalloc(sizeof(*adma), GFP_KERNEL); 1701b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko if (!adma) 1711b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko return -ENOMEM; 1721b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko 1731b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko adma->dev = dev; 1741b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko adma->acpi_dma_xlate = acpi_dma_xlate; 1751b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko adma->data = data; 1761b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko 177ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko acpi_dma_parse_csrt(adev, adma); 178ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko 1791b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko /* Now queue acpi_dma controller structure in list */ 1801b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko mutex_lock(&acpi_dma_lock); 1811b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko list_add_tail(&adma->dma_controllers, &acpi_dma_list); 1821b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko mutex_unlock(&acpi_dma_lock); 1831b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko 1841b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko return 0; 1851b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko} 1861b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy ShevchenkoEXPORT_SYMBOL_GPL(acpi_dma_controller_register); 1871b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko 1881b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko/** 1891b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * acpi_dma_controller_free - Remove a DMA controller from ACPI DMA helpers list 1901b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * @dev: struct device of DMA controller 1911b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * 1921b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * Memory allocated by acpi_dma_controller_register() is freed here. 19339d1447811fef1262ba956aac719c90a0f7b257fAndy Shevchenko * 19439d1447811fef1262ba956aac719c90a0f7b257fAndy Shevchenko * Return: 19539d1447811fef1262ba956aac719c90a0f7b257fAndy Shevchenko * 0 on success or appropriate errno value on error. 1961b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko */ 1971b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenkoint acpi_dma_controller_free(struct device *dev) 1981b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko{ 1991b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko struct acpi_dma *adma; 2001b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko 2011b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko if (!dev) 2021b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko return -EINVAL; 2031b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko 2041b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko mutex_lock(&acpi_dma_lock); 2051b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko 2061b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko list_for_each_entry(adma, &acpi_dma_list, dma_controllers) 2071b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko if (adma->dev == dev) { 2081b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko list_del(&adma->dma_controllers); 2091b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko mutex_unlock(&acpi_dma_lock); 2101b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko kfree(adma); 2111b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko return 0; 2121b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko } 2131b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko 2141b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko mutex_unlock(&acpi_dma_lock); 2151b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko return -ENODEV; 2161b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko} 2171b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy ShevchenkoEXPORT_SYMBOL_GPL(acpi_dma_controller_free); 2181b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko 2191b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenkostatic void devm_acpi_dma_release(struct device *dev, void *res) 2201b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko{ 2211b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko acpi_dma_controller_free(dev); 2221b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko} 2231b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko 2241b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko/** 2251b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * devm_acpi_dma_controller_register - resource managed acpi_dma_controller_register() 2261b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * @dev: device that is registering this DMA controller 2271b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * @acpi_dma_xlate: translation function 2281b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * @data pointer to controller specific data 2291b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * 2301b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * Managed acpi_dma_controller_register(). DMA controller registered by this 2311b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * function are automatically freed on driver detach. See 2321b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * acpi_dma_controller_register() for more information. 23339d1447811fef1262ba956aac719c90a0f7b257fAndy Shevchenko * 23439d1447811fef1262ba956aac719c90a0f7b257fAndy Shevchenko * Return: 23539d1447811fef1262ba956aac719c90a0f7b257fAndy Shevchenko * 0 on success or appropriate errno value on error. 2361b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko */ 2371b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenkoint devm_acpi_dma_controller_register(struct device *dev, 2381b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko struct dma_chan *(*acpi_dma_xlate) 2391b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko (struct acpi_dma_spec *, struct acpi_dma *), 2401b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko void *data) 2411b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko{ 2421b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko void *res; 2431b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko int ret; 2441b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko 2451b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko res = devres_alloc(devm_acpi_dma_release, 0, GFP_KERNEL); 2461b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko if (!res) 2471b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko return -ENOMEM; 2481b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko 2491b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko ret = acpi_dma_controller_register(dev, acpi_dma_xlate, data); 2501b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko if (ret) { 2511b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko devres_free(res); 2521b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko return ret; 2531b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko } 2541b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko devres_add(dev, res); 2551b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko return 0; 2561b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko} 2571b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy ShevchenkoEXPORT_SYMBOL_GPL(devm_acpi_dma_controller_register); 2581b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko 2591b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko/** 2601b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * devm_acpi_dma_controller_free - resource managed acpi_dma_controller_free() 2611b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * 2621b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * Unregister a DMA controller registered with 2631b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * devm_acpi_dma_controller_register(). Normally this function will not need to 2641b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * be called and the resource management code will ensure that the resource is 2651b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * freed. 2661b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko */ 2671b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenkovoid devm_acpi_dma_controller_free(struct device *dev) 2681b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko{ 2698f01258385be3225331d7edd20de905df433aac4Andy Shevchenko WARN_ON(devres_release(dev, devm_acpi_dma_release, NULL, NULL)); 2701b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko} 2711b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy ShevchenkoEXPORT_SYMBOL_GPL(devm_acpi_dma_controller_free); 2721b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko 273ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko/** 274ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko * acpi_dma_update_dma_spec - prepare dma specifier to pass to translation function 275ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko * @adma: struct acpi_dma of DMA controller 276ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko * @dma_spec: dma specifier to update 277ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko * 278ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko * Accordingly to ACPI 5.0 Specification Table 6-170 "Fixed DMA Resource 279ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko * Descriptor": 280ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko * DMA Request Line bits is a platform-relative number uniquely 281ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko * identifying the request line assigned. Request line-to-Controller 282ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko * mapping is done in a controller-specific OS driver. 283ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko * That's why we can safely adjust slave_id when the appropriate controller is 284ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko * found. 28539d1447811fef1262ba956aac719c90a0f7b257fAndy Shevchenko * 28639d1447811fef1262ba956aac719c90a0f7b257fAndy Shevchenko * Return: 28739d1447811fef1262ba956aac719c90a0f7b257fAndy Shevchenko * 0, if no information is avaiable, -1 on mismatch, and 1 otherwise. 288ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko */ 289ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenkostatic int acpi_dma_update_dma_spec(struct acpi_dma *adma, 290ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko struct acpi_dma_spec *dma_spec) 291ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko{ 292ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko /* Set link to the DMA controller device */ 293ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko dma_spec->dev = adma->dev; 294ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko 295ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko /* Check if the request line range is available */ 296ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko if (adma->base_request_line == 0 && adma->end_request_line == 0) 297ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko return 0; 298ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko 299ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko /* Check if slave_id falls to the range */ 300ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko if (dma_spec->slave_id < adma->base_request_line || 301ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko dma_spec->slave_id > adma->end_request_line) 302ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko return -1; 303ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko 304ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko /* 305ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko * Here we adjust slave_id. It should be a relative number to the base 306ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko * request line. 307ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko */ 308ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko dma_spec->slave_id -= adma->base_request_line; 309ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko 310ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko return 1; 311ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko} 312ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko 3131b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenkostruct acpi_dma_parser_data { 3141b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko struct acpi_dma_spec dma_spec; 3151b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko size_t index; 3161b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko size_t n; 3171b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko}; 3181b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko 3191b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko/** 3201b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * acpi_dma_parse_fixed_dma - Parse FixedDMA ACPI resources to a DMA specifier 3211b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * @res: struct acpi_resource to get FixedDMA resources from 3221b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * @data: pointer to a helper struct acpi_dma_parser_data 3231b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko */ 3241b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenkostatic int acpi_dma_parse_fixed_dma(struct acpi_resource *res, void *data) 3251b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko{ 3261b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko struct acpi_dma_parser_data *pdata = data; 3271b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko 3281b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko if (res->type == ACPI_RESOURCE_TYPE_FIXED_DMA) { 3291b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko struct acpi_resource_fixed_dma *dma = &res->data.fixed_dma; 3301b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko 3311b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko if (pdata->n++ == pdata->index) { 3321b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko pdata->dma_spec.chan_id = dma->channels; 3331b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko pdata->dma_spec.slave_id = dma->request_lines; 3341b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko } 3351b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko } 3361b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko 3371b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko /* Tell the ACPI core to skip this resource */ 3381b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko return 1; 3391b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko} 3401b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko 3411b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko/** 3421b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * acpi_dma_request_slave_chan_by_index - Get the DMA slave channel 3431b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * @dev: struct device to get DMA request from 3441b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * @index: index of FixedDMA descriptor for @dev 3451b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * 34639d1447811fef1262ba956aac719c90a0f7b257fAndy Shevchenko * Return: 3470f6a928d035b82c0b3aa387d510a73f3e6dbf8e3Andy Shevchenko * Pointer to appropriate dma channel on success or an error pointer. 3481b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko */ 3491b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenkostruct dma_chan *acpi_dma_request_slave_chan_by_index(struct device *dev, 3501b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko size_t index) 3511b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko{ 3521b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko struct acpi_dma_parser_data pdata; 3531b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko struct acpi_dma_spec *dma_spec = &pdata.dma_spec; 3541b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko struct list_head resource_list; 3551b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko struct acpi_device *adev; 3561b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko struct acpi_dma *adma; 3571b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko struct dma_chan *chan = NULL; 358ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko int found; 3591b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko 3601b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko /* Check if the device was enumerated by ACPI */ 3611b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko if (!dev || !ACPI_HANDLE(dev)) 3620f6a928d035b82c0b3aa387d510a73f3e6dbf8e3Andy Shevchenko return ERR_PTR(-ENODEV); 3631b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko 3641b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko if (acpi_bus_get_device(ACPI_HANDLE(dev), &adev)) 3650f6a928d035b82c0b3aa387d510a73f3e6dbf8e3Andy Shevchenko return ERR_PTR(-ENODEV); 3661b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko 3671b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko memset(&pdata, 0, sizeof(pdata)); 3681b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko pdata.index = index; 3691b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko 3701b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko /* Initial values for the request line and channel */ 3711b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko dma_spec->chan_id = -1; 3721b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko dma_spec->slave_id = -1; 3731b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko 3741b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko INIT_LIST_HEAD(&resource_list); 3751b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko acpi_dev_get_resources(adev, &resource_list, 3761b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko acpi_dma_parse_fixed_dma, &pdata); 3771b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko acpi_dev_free_resource_list(&resource_list); 3781b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko 3791b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko if (dma_spec->slave_id < 0 || dma_spec->chan_id < 0) 3800f6a928d035b82c0b3aa387d510a73f3e6dbf8e3Andy Shevchenko return ERR_PTR(-ENODEV); 3811b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko 3821b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko mutex_lock(&acpi_dma_lock); 3831b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko 3841b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko list_for_each_entry(adma, &acpi_dma_list, dma_controllers) { 385ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko /* 386ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko * We are not going to call translation function if slave_id 387ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko * doesn't fall to the request range. 388ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko */ 389ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko found = acpi_dma_update_dma_spec(adma, dma_spec); 390ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko if (found < 0) 391ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko continue; 3921b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko chan = adma->acpi_dma_xlate(dma_spec, adma); 393ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko /* 394ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko * Try to get a channel only from the DMA controller that 395ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko * matches the slave_id. See acpi_dma_update_dma_spec() 396ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko * description for the details. 397ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko */ 398ee8209fd026b074bb8eb75bece516a338a281b1bAndy Shevchenko if (found > 0 || chan) 3991b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko break; 4001b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko } 4011b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko 4021b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko mutex_unlock(&acpi_dma_lock); 4030f6a928d035b82c0b3aa387d510a73f3e6dbf8e3Andy Shevchenko return chan ? chan : ERR_PTR(-EPROBE_DEFER); 4041b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko} 4051b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy ShevchenkoEXPORT_SYMBOL_GPL(acpi_dma_request_slave_chan_by_index); 4061b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko 4071b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko/** 4081b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * acpi_dma_request_slave_chan_by_name - Get the DMA slave channel 4091b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * @dev: struct device to get DMA request from 4101b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * @name: represents corresponding FixedDMA descriptor for @dev 4111b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * 4121b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * In order to support both Device Tree and ACPI in a single driver we 4131b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * translate the names "tx" and "rx" here based on the most common case where 4141b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * the first FixedDMA descriptor is TX and second is RX. 4151b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * 41639d1447811fef1262ba956aac719c90a0f7b257fAndy Shevchenko * Return: 4170f6a928d035b82c0b3aa387d510a73f3e6dbf8e3Andy Shevchenko * Pointer to appropriate dma channel on success or an error pointer. 4181b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko */ 4191b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenkostruct dma_chan *acpi_dma_request_slave_chan_by_name(struct device *dev, 4201b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko const char *name) 4211b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko{ 4221b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko size_t index; 4231b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko 4241b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko if (!strcmp(name, "tx")) 4251b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko index = 0; 4261b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko else if (!strcmp(name, "rx")) 4271b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko index = 1; 4281b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko else 4290f6a928d035b82c0b3aa387d510a73f3e6dbf8e3Andy Shevchenko return ERR_PTR(-ENODEV); 4301b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko 4311b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko return acpi_dma_request_slave_chan_by_index(dev, index); 4321b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko} 4331b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy ShevchenkoEXPORT_SYMBOL_GPL(acpi_dma_request_slave_chan_by_name); 4341b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko 4351b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko/** 4361b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * acpi_dma_simple_xlate - Simple ACPI DMA engine translation helper 4371b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * @dma_spec: pointer to ACPI DMA specifier 4381b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * @adma: pointer to ACPI DMA controller data 4391b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * 4401b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko * A simple translation function for ACPI based devices. Passes &struct 44139d1447811fef1262ba956aac719c90a0f7b257fAndy Shevchenko * dma_spec to the DMA controller driver provided filter function. 44239d1447811fef1262ba956aac719c90a0f7b257fAndy Shevchenko * 44339d1447811fef1262ba956aac719c90a0f7b257fAndy Shevchenko * Return: 44439d1447811fef1262ba956aac719c90a0f7b257fAndy Shevchenko * Pointer to the channel if found or %NULL otherwise. 4451b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko */ 4461b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenkostruct dma_chan *acpi_dma_simple_xlate(struct acpi_dma_spec *dma_spec, 4471b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko struct acpi_dma *adma) 4481b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko{ 4491b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko struct acpi_dma_filter_info *info = adma->data; 4501b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko 4511b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko if (!info || !info->filter_fn) 4521b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko return NULL; 4531b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko 4541b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko return dma_request_channel(info->dma_cap, info->filter_fn, dma_spec); 4551b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy Shevchenko} 4561b2e98bc1e35ebe1f65c3db62c8317096ad7f2c8Andy ShevchenkoEXPORT_SYMBOL_GPL(acpi_dma_simple_xlate); 457