Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * ACPI helpers for DMA request / controller
0004  *
0005  * Based on of-dma.c
0006  *
0007  * Copyright (C) 2013, Intel Corporation
0008  * Authors: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
0009  *      Mika Westerberg <mika.westerberg@linux.intel.com>
0010  */
0011 
0012 #include <linux/device.h>
0013 #include <linux/dma-mapping.h>
0014 #include <linux/err.h>
0015 #include <linux/module.h>
0016 #include <linux/kernel.h>
0017 #include <linux/list.h>
0018 #include <linux/mutex.h>
0019 #include <linux/slab.h>
0020 #include <linux/ioport.h>
0021 #include <linux/acpi.h>
0022 #include <linux/acpi_dma.h>
0023 #include <linux/property.h>
0024 
0025 static LIST_HEAD(acpi_dma_list);
0026 static DEFINE_MUTEX(acpi_dma_lock);
0027 
0028 /**
0029  * acpi_dma_parse_resource_group - match device and parse resource group
0030  * @grp:    CSRT resource group
0031  * @adev:   ACPI device to match with
0032  * @adma:   struct acpi_dma of the given DMA controller
0033  *
0034  * In order to match a device from DSDT table to the corresponding CSRT device
0035  * we use MMIO address and IRQ.
0036  *
0037  * Return:
0038  * 1 on success, 0 when no information is available, or appropriate errno value
0039  * on error.
0040  */
0041 static int acpi_dma_parse_resource_group(const struct acpi_csrt_group *grp,
0042         struct acpi_device *adev, struct acpi_dma *adma)
0043 {
0044     const struct acpi_csrt_shared_info *si;
0045     struct list_head resource_list;
0046     struct resource_entry *rentry;
0047     resource_size_t mem = 0, irq = 0;
0048     int ret;
0049 
0050     if (grp->shared_info_length != sizeof(struct acpi_csrt_shared_info))
0051         return -ENODEV;
0052 
0053     INIT_LIST_HEAD(&resource_list);
0054     ret = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
0055     if (ret <= 0)
0056         return 0;
0057 
0058     list_for_each_entry(rentry, &resource_list, node) {
0059         if (resource_type(rentry->res) == IORESOURCE_MEM)
0060             mem = rentry->res->start;
0061         else if (resource_type(rentry->res) == IORESOURCE_IRQ)
0062             irq = rentry->res->start;
0063     }
0064 
0065     acpi_dev_free_resource_list(&resource_list);
0066 
0067     /* Consider initial zero values as resource not found */
0068     if (mem == 0 && irq == 0)
0069         return 0;
0070 
0071     si = (const struct acpi_csrt_shared_info *)&grp[1];
0072 
0073     /* Match device by MMIO */
0074     if (si->mmio_base_low != lower_32_bits(mem) ||
0075         si->mmio_base_high != upper_32_bits(mem))
0076         return 0;
0077 
0078     /*
0079      * acpi_gsi_to_irq() can't be used because some platforms do not save
0080      * registered IRQs in the MP table. Instead we just try to register
0081      * the GSI, which is the core part of the above mentioned function.
0082      */
0083     ret = acpi_register_gsi(NULL, si->gsi_interrupt, si->interrupt_mode, si->interrupt_polarity);
0084     if (ret < 0)
0085         return 0;
0086 
0087     /* Match device by Linux vIRQ */
0088     if (ret != irq)
0089         return 0;
0090 
0091     dev_dbg(&adev->dev, "matches with %.4s%04X (rev %u)\n",
0092         (char *)&grp->vendor_id, grp->device_id, grp->revision);
0093 
0094     /* Check if the request line range is available */
0095     if (si->base_request_line == 0 && si->num_handshake_signals == 0)
0096         return 0;
0097 
0098     /* Set up DMA mask based on value from CSRT */
0099     ret = dma_coerce_mask_and_coherent(&adev->dev,
0100                        DMA_BIT_MASK(si->dma_address_width));
0101     if (ret)
0102         return 0;
0103 
0104     adma->base_request_line = si->base_request_line;
0105     adma->end_request_line = si->base_request_line +
0106                  si->num_handshake_signals - 1;
0107 
0108     dev_dbg(&adev->dev, "request line base: 0x%04x end: 0x%04x\n",
0109         adma->base_request_line, adma->end_request_line);
0110 
0111     return 1;
0112 }
0113 
0114 /**
0115  * acpi_dma_parse_csrt - parse CSRT to exctract additional DMA resources
0116  * @adev:   ACPI device to match with
0117  * @adma:   struct acpi_dma of the given DMA controller
0118  *
0119  * CSRT or Core System Resources Table is a proprietary ACPI table
0120  * introduced by Microsoft. This table can contain devices that are not in
0121  * the system DSDT table. In particular DMA controllers might be described
0122  * here.
0123  *
0124  * We are using this table to get the request line range of the specific DMA
0125  * controller to be used later.
0126  */
0127 static void acpi_dma_parse_csrt(struct acpi_device *adev, struct acpi_dma *adma)
0128 {
0129     struct acpi_csrt_group *grp, *end;
0130     struct acpi_table_csrt *csrt;
0131     acpi_status status;
0132     int ret;
0133 
0134     status = acpi_get_table(ACPI_SIG_CSRT, 0,
0135                 (struct acpi_table_header **)&csrt);
0136     if (ACPI_FAILURE(status)) {
0137         if (status != AE_NOT_FOUND)
0138             dev_warn(&adev->dev, "failed to get the CSRT table\n");
0139         return;
0140     }
0141 
0142     grp = (struct acpi_csrt_group *)(csrt + 1);
0143     end = (struct acpi_csrt_group *)((void *)csrt + csrt->header.length);
0144 
0145     while (grp < end) {
0146         ret = acpi_dma_parse_resource_group(grp, adev, adma);
0147         if (ret < 0) {
0148             dev_warn(&adev->dev,
0149                  "error in parsing resource group\n");
0150             break;
0151         }
0152 
0153         grp = (struct acpi_csrt_group *)((void *)grp + grp->length);
0154     }
0155 
0156     acpi_put_table((struct acpi_table_header *)csrt);
0157 }
0158 
0159 /**
0160  * acpi_dma_controller_register - Register a DMA controller to ACPI DMA helpers
0161  * @dev:        struct device of DMA controller
0162  * @acpi_dma_xlate: translation function which converts a dma specifier
0163  *          into a dma_chan structure
0164  * @data:       pointer to controller specific data to be used by
0165  *          translation function
0166  *
0167  * Allocated memory should be freed with appropriate acpi_dma_controller_free()
0168  * call.
0169  *
0170  * Return:
0171  * 0 on success or appropriate errno value on error.
0172  */
0173 int acpi_dma_controller_register(struct device *dev,
0174         struct dma_chan *(*acpi_dma_xlate)
0175         (struct acpi_dma_spec *, struct acpi_dma *),
0176         void *data)
0177 {
0178     struct acpi_device *adev;
0179     struct acpi_dma *adma;
0180 
0181     if (!dev || !acpi_dma_xlate)
0182         return -EINVAL;
0183 
0184     /* Check if the device was enumerated by ACPI */
0185     adev = ACPI_COMPANION(dev);
0186     if (!adev)
0187         return -EINVAL;
0188 
0189     adma = kzalloc(sizeof(*adma), GFP_KERNEL);
0190     if (!adma)
0191         return -ENOMEM;
0192 
0193     adma->dev = dev;
0194     adma->acpi_dma_xlate = acpi_dma_xlate;
0195     adma->data = data;
0196 
0197     acpi_dma_parse_csrt(adev, adma);
0198 
0199     /* Now queue acpi_dma controller structure in list */
0200     mutex_lock(&acpi_dma_lock);
0201     list_add_tail(&adma->dma_controllers, &acpi_dma_list);
0202     mutex_unlock(&acpi_dma_lock);
0203 
0204     return 0;
0205 }
0206 EXPORT_SYMBOL_GPL(acpi_dma_controller_register);
0207 
0208 /**
0209  * acpi_dma_controller_free - Remove a DMA controller from ACPI DMA helpers list
0210  * @dev:    struct device of DMA controller
0211  *
0212  * Memory allocated by acpi_dma_controller_register() is freed here.
0213  *
0214  * Return:
0215  * 0 on success or appropriate errno value on error.
0216  */
0217 int acpi_dma_controller_free(struct device *dev)
0218 {
0219     struct acpi_dma *adma;
0220 
0221     if (!dev)
0222         return -EINVAL;
0223 
0224     mutex_lock(&acpi_dma_lock);
0225 
0226     list_for_each_entry(adma, &acpi_dma_list, dma_controllers)
0227         if (adma->dev == dev) {
0228             list_del(&adma->dma_controllers);
0229             mutex_unlock(&acpi_dma_lock);
0230             kfree(adma);
0231             return 0;
0232         }
0233 
0234     mutex_unlock(&acpi_dma_lock);
0235     return -ENODEV;
0236 }
0237 EXPORT_SYMBOL_GPL(acpi_dma_controller_free);
0238 
0239 static void devm_acpi_dma_release(struct device *dev, void *res)
0240 {
0241     acpi_dma_controller_free(dev);
0242 }
0243 
0244 /**
0245  * devm_acpi_dma_controller_register - resource managed acpi_dma_controller_register()
0246  * @dev:        device that is registering this DMA controller
0247  * @acpi_dma_xlate: translation function
0248  * @data:       pointer to controller specific data
0249  *
0250  * Managed acpi_dma_controller_register(). DMA controller registered by this
0251  * function are automatically freed on driver detach. See
0252  * acpi_dma_controller_register() for more information.
0253  *
0254  * Return:
0255  * 0 on success or appropriate errno value on error.
0256  */
0257 int devm_acpi_dma_controller_register(struct device *dev,
0258         struct dma_chan *(*acpi_dma_xlate)
0259         (struct acpi_dma_spec *, struct acpi_dma *),
0260         void *data)
0261 {
0262     void *res;
0263     int ret;
0264 
0265     res = devres_alloc(devm_acpi_dma_release, 0, GFP_KERNEL);
0266     if (!res)
0267         return -ENOMEM;
0268 
0269     ret = acpi_dma_controller_register(dev, acpi_dma_xlate, data);
0270     if (ret) {
0271         devres_free(res);
0272         return ret;
0273     }
0274     devres_add(dev, res);
0275     return 0;
0276 }
0277 EXPORT_SYMBOL_GPL(devm_acpi_dma_controller_register);
0278 
0279 /**
0280  * devm_acpi_dma_controller_free - resource managed acpi_dma_controller_free()
0281  * @dev:    device that is unregistering as DMA controller
0282  *
0283  * Unregister a DMA controller registered with
0284  * devm_acpi_dma_controller_register(). Normally this function will not need to
0285  * be called and the resource management code will ensure that the resource is
0286  * freed.
0287  */
0288 void devm_acpi_dma_controller_free(struct device *dev)
0289 {
0290     WARN_ON(devres_release(dev, devm_acpi_dma_release, NULL, NULL));
0291 }
0292 EXPORT_SYMBOL_GPL(devm_acpi_dma_controller_free);
0293 
0294 /**
0295  * acpi_dma_update_dma_spec - prepare dma specifier to pass to translation function
0296  * @adma:   struct acpi_dma of DMA controller
0297  * @dma_spec:   dma specifier to update
0298  *
0299  * Accordingly to ACPI 5.0 Specification Table 6-170 "Fixed DMA Resource
0300  * Descriptor":
0301  *  DMA Request Line bits is a platform-relative number uniquely
0302  *  identifying the request line assigned. Request line-to-Controller
0303  *  mapping is done in a controller-specific OS driver.
0304  * That's why we can safely adjust slave_id when the appropriate controller is
0305  * found.
0306  *
0307  * Return:
0308  * 0, if no information is avaiable, -1 on mismatch, and 1 otherwise.
0309  */
0310 static int acpi_dma_update_dma_spec(struct acpi_dma *adma,
0311         struct acpi_dma_spec *dma_spec)
0312 {
0313     /* Set link to the DMA controller device */
0314     dma_spec->dev = adma->dev;
0315 
0316     /* Check if the request line range is available */
0317     if (adma->base_request_line == 0 && adma->end_request_line == 0)
0318         return 0;
0319 
0320     /* Check if slave_id falls to the range */
0321     if (dma_spec->slave_id < adma->base_request_line ||
0322         dma_spec->slave_id > adma->end_request_line)
0323         return -1;
0324 
0325     /*
0326      * Here we adjust slave_id. It should be a relative number to the base
0327      * request line.
0328      */
0329     dma_spec->slave_id -= adma->base_request_line;
0330 
0331     return 1;
0332 }
0333 
0334 struct acpi_dma_parser_data {
0335     struct acpi_dma_spec dma_spec;
0336     size_t index;
0337     size_t n;
0338 };
0339 
0340 /**
0341  * acpi_dma_parse_fixed_dma - Parse FixedDMA ACPI resources to a DMA specifier
0342  * @res:    struct acpi_resource to get FixedDMA resources from
0343  * @data:   pointer to a helper struct acpi_dma_parser_data
0344  */
0345 static int acpi_dma_parse_fixed_dma(struct acpi_resource *res, void *data)
0346 {
0347     struct acpi_dma_parser_data *pdata = data;
0348 
0349     if (res->type == ACPI_RESOURCE_TYPE_FIXED_DMA) {
0350         struct acpi_resource_fixed_dma *dma = &res->data.fixed_dma;
0351 
0352         if (pdata->n++ == pdata->index) {
0353             pdata->dma_spec.chan_id = dma->channels;
0354             pdata->dma_spec.slave_id = dma->request_lines;
0355         }
0356     }
0357 
0358     /* Tell the ACPI core to skip this resource */
0359     return 1;
0360 }
0361 
0362 /**
0363  * acpi_dma_request_slave_chan_by_index - Get the DMA slave channel
0364  * @dev:    struct device to get DMA request from
0365  * @index:  index of FixedDMA descriptor for @dev
0366  *
0367  * Return:
0368  * Pointer to appropriate dma channel on success or an error pointer.
0369  */
0370 struct dma_chan *acpi_dma_request_slave_chan_by_index(struct device *dev,
0371         size_t index)
0372 {
0373     struct acpi_dma_parser_data pdata;
0374     struct acpi_dma_spec *dma_spec = &pdata.dma_spec;
0375     struct acpi_device *adev = ACPI_COMPANION(dev);
0376     struct list_head resource_list;
0377     struct acpi_dma *adma;
0378     struct dma_chan *chan = NULL;
0379     int found;
0380     int ret;
0381 
0382     memset(&pdata, 0, sizeof(pdata));
0383     pdata.index = index;
0384 
0385     /* Initial values for the request line and channel */
0386     dma_spec->chan_id = -1;
0387     dma_spec->slave_id = -1;
0388 
0389     INIT_LIST_HEAD(&resource_list);
0390     ret = acpi_dev_get_resources(adev, &resource_list,
0391                      acpi_dma_parse_fixed_dma, &pdata);
0392     acpi_dev_free_resource_list(&resource_list);
0393     if (ret < 0)
0394         return ERR_PTR(ret);
0395 
0396     if (dma_spec->slave_id < 0 || dma_spec->chan_id < 0)
0397         return ERR_PTR(-ENODEV);
0398 
0399     mutex_lock(&acpi_dma_lock);
0400 
0401     list_for_each_entry(adma, &acpi_dma_list, dma_controllers) {
0402         /*
0403          * We are not going to call translation function if slave_id
0404          * doesn't fall to the request range.
0405          */
0406         found = acpi_dma_update_dma_spec(adma, dma_spec);
0407         if (found < 0)
0408             continue;
0409         chan = adma->acpi_dma_xlate(dma_spec, adma);
0410         /*
0411          * Try to get a channel only from the DMA controller that
0412          * matches the slave_id. See acpi_dma_update_dma_spec()
0413          * description for the details.
0414          */
0415         if (found > 0 || chan)
0416             break;
0417     }
0418 
0419     mutex_unlock(&acpi_dma_lock);
0420     return chan ? chan : ERR_PTR(-EPROBE_DEFER);
0421 }
0422 EXPORT_SYMBOL_GPL(acpi_dma_request_slave_chan_by_index);
0423 
0424 /**
0425  * acpi_dma_request_slave_chan_by_name - Get the DMA slave channel
0426  * @dev:    struct device to get DMA request from
0427  * @name:   represents corresponding FixedDMA descriptor for @dev
0428  *
0429  * In order to support both Device Tree and ACPI in a single driver we
0430  * translate the names "tx" and "rx" here based on the most common case where
0431  * the first FixedDMA descriptor is TX and second is RX.
0432  *
0433  * If the device has "dma-names" property the FixedDMA descriptor indices
0434  * are retrieved based on those. Otherwise the function falls back using
0435  * hardcoded indices.
0436  *
0437  * Return:
0438  * Pointer to appropriate dma channel on success or an error pointer.
0439  */
0440 struct dma_chan *acpi_dma_request_slave_chan_by_name(struct device *dev,
0441         const char *name)
0442 {
0443     int index;
0444 
0445     index = device_property_match_string(dev, "dma-names", name);
0446     if (index < 0) {
0447         if (!strcmp(name, "tx"))
0448             index = 0;
0449         else if (!strcmp(name, "rx"))
0450             index = 1;
0451         else
0452             return ERR_PTR(-ENODEV);
0453     }
0454 
0455     dev_dbg(dev, "Looking for DMA channel \"%s\" at index %d...\n", name, index);
0456     return acpi_dma_request_slave_chan_by_index(dev, index);
0457 }
0458 EXPORT_SYMBOL_GPL(acpi_dma_request_slave_chan_by_name);
0459 
0460 /**
0461  * acpi_dma_simple_xlate - Simple ACPI DMA engine translation helper
0462  * @dma_spec: pointer to ACPI DMA specifier
0463  * @adma: pointer to ACPI DMA controller data
0464  *
0465  * A simple translation function for ACPI based devices. Passes &struct
0466  * dma_spec to the DMA controller driver provided filter function.
0467  *
0468  * Return:
0469  * Pointer to the channel if found or %NULL otherwise.
0470  */
0471 struct dma_chan *acpi_dma_simple_xlate(struct acpi_dma_spec *dma_spec,
0472         struct acpi_dma *adma)
0473 {
0474     struct acpi_dma_filter_info *info = adma->data;
0475 
0476     if (!info || !info->filter_fn)
0477         return NULL;
0478 
0479     return dma_request_channel(info->dma_cap, info->filter_fn, dma_spec);
0480 }
0481 EXPORT_SYMBOL_GPL(acpi_dma_simple_xlate);