diff options
author | Laurentiu Tudor <laurentiu.tudor@nxp.com> | 2020-02-13 11:59:12 +0200 |
---|---|---|
committer | Russell King <rmk+kernel@armlinux.org.uk> | 2020-10-12 22:45:01 +0100 |
commit | 5804a6c03966ed6abc3979e10435362a1cd72505 (patch) | |
tree | 59899b4eb3f657c4e3e25290876c5d31e050b381 | |
parent | d58771f9003196ae9f1b2db68f3b61cd41c7ceda (diff) |
bus: fsl-mc: add custom .dma_configure implementation
The devices on this bus are not discovered by way of device tree
but by queries to the firmware. It makes little sense to trick the
generic of layer into thinking that these devices are of related so
that we can get our dma configuration. Instead of doing that, add
our custom dma configuration implementation.
Signed-off-by: Laurentiu Tudor <laurentiu.tudor@nxp.com>
-rw-r--r-- | drivers/bus/fsl-mc/fsl-mc-bus.c | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c index 836ee25d5951..ce3d81b84f7f 100644 --- a/drivers/bus/fsl-mc/fsl-mc-bus.c +++ b/drivers/bus/fsl-mc/fsl-mc-bus.c @@ -128,14 +128,56 @@ static int fsl_mc_dma_configure(struct device *dev) struct device *dma_dev = dev; struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); u32 input_id = mc_dev->icid; + struct iommu_fwspec *fwspec; + const struct iommu_ops *iommu_ops; + int ret; + + /* Skip DMA setup for devices that are not DMA masters */ + if (dev->type == &fsl_mc_bus_dpmcp_type || + dev->type == &fsl_mc_bus_dpbp_type || + dev->type == &fsl_mc_bus_dpcon_type || + dev->type == &fsl_mc_bus_dpio_type) + return 0; while (dev_is_fsl_mc(dma_dev)) dma_dev = dma_dev->parent; + +#if 0 if (dev_of_node(dma_dev)) return of_dma_configure_id(dev, dma_dev->of_node, 0, &input_id); return acpi_dma_configure_id(dev, DEV_DMA_COHERENT, &input_id); +#else + fwspec = dev_iommu_fwspec_get(dma_dev); + if (!fwspec) + return -ENODEV; + iommu_ops = iommu_ops_from_fwnode(fwspec->iommu_fwnode); + if (!iommu_ops) + return -ENODEV; + + ret = iommu_fwspec_init(dev, fwspec->iommu_fwnode, iommu_ops); + if (ret) + return ret; + + ret = iommu_fwspec_add_ids(dev, &input_id, 1); + if (ret) { + iommu_fwspec_free(dev); + return ret; + } + + if (!device_iommu_mapped(dev)) { + ret = iommu_probe_device(dev); + if (ret) { + iommu_fwspec_free(dev); + return ret; + } + } + + arch_setup_dma_ops(dev, 0, *dma_dev->dma_mask + 1, iommu_ops, true); + + return 0; +#endif } static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, |