summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurentiu Tudor <laurentiu.tudor@nxp.com>2020-02-13 11:59:12 +0200
committerRussell King <rmk+kernel@armlinux.org.uk>2020-10-12 22:45:01 +0100
commit5804a6c03966ed6abc3979e10435362a1cd72505 (patch)
tree59899b4eb3f657c4e3e25290876c5d31e050b381
parentd58771f9003196ae9f1b2db68f3b61cd41c7ceda (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.c42
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,