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