root/drivers/dma/acpi-dma.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. acpi_dma_parse_resource_group
  2. acpi_dma_parse_csrt
  3. acpi_dma_controller_register
  4. acpi_dma_controller_free
  5. devm_acpi_dma_release
  6. devm_acpi_dma_controller_register
  7. devm_acpi_dma_controller_free
  8. acpi_dma_update_dma_spec
  9. acpi_dma_parse_fixed_dma
  10. acpi_dma_request_slave_chan_by_index
  11. acpi_dma_request_slave_chan_by_name
  12. acpi_dma_simple_xlate

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

/* [<][>][^][v][top][bottom][index][help] */