summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorNipun Gupta <nipun.gupta@nxp.com>2017-04-17 20:27:17 (GMT)
committerXie Xiaobo <xiaobo.xie@nxp.com>2017-09-25 07:25:17 (GMT)
commitd66cebc5f4cc19589efb86b68e4d13cb14e2715d (patch)
tree533e9f3bfc07e3d90fe25de23b92b242a8eb6b4f /drivers
parent614c461eed9413ea40e45b68b46b481caa578124 (diff)
downloadlinux-d66cebc5f4cc19589efb86b68e4d13cb14e2715d.tar.xz
staging: fsl-mc: Configure the SMMU using 'iommu-map' DT property
fsl-mc devices needs to configure SMMU driver using the 'iommu-map' property. They first create the iommu_fwspec and then populate it with the stream-id and smr mask before the device gets registered with the SMMU driver. Signed-off-by: Nipun Gupta <nipun.gupta@nxp.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/staging/fsl-mc/bus/Makefile3
-rw-r--r--drivers/staging/fsl-mc/bus/fsl-mc-bus.c17
-rw-r--r--drivers/staging/fsl-mc/bus/fsl-mc-iommu.c78
-rw-r--r--drivers/staging/fsl-mc/include/mc.h3
4 files changed, 97 insertions, 4 deletions
diff --git a/drivers/staging/fsl-mc/bus/Makefile b/drivers/staging/fsl-mc/bus/Makefile
index 39248ac..e7e2239 100644
--- a/drivers/staging/fsl-mc/bus/Makefile
+++ b/drivers/staging/fsl-mc/bus/Makefile
@@ -18,7 +18,8 @@ mc-bus-driver-objs := fsl-mc-bus.o \
irq-gic-v3-its-fsl-mc-msi.o \
dpmcp.o \
dpbp.o \
- dpcon.o
+ dpcon.o \
+ fsl-mc-iommu.o
# MC DPIO driver
obj-$(CONFIG_FSL_MC_DPIO) += dpio/
diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c b/drivers/staging/fsl-mc/bus/fsl-mc-bus.c
index b1defca..f38efea 100644
--- a/drivers/staging/fsl-mc/bus/fsl-mc-bus.c
+++ b/drivers/staging/fsl-mc/bus/fsl-mc-bus.c
@@ -521,6 +521,8 @@ int fsl_mc_device_add(struct dprc_obj_desc *obj_desc,
struct fsl_mc_device *mc_dev = NULL;
struct fsl_mc_bus *mc_bus = NULL;
struct fsl_mc_device *parent_mc_dev;
+ struct device *fsl_mc_platform_dev;
+ struct device_node *fsl_mc_platform_node;
if (dev_is_fsl_mc(parent_dev))
parent_mc_dev = to_fsl_mc_device(parent_dev);
@@ -613,9 +615,14 @@ int fsl_mc_device_add(struct dprc_obj_desc *obj_desc,
goto error_cleanup_dev;
}
- /* Objects are coherent, unless 'no shareability' flag set. */
- if (!(obj_desc->flags & DPRC_OBJ_FLAG_NO_MEM_SHAREABILITY))
- arch_setup_dma_ops(&mc_dev->dev, 0, 0, NULL, true);
+ fsl_mc_platform_dev = &mc_dev->dev;
+ while (dev_is_fsl_mc(fsl_mc_platform_dev))
+ fsl_mc_platform_dev = fsl_mc_platform_dev->parent;
+ fsl_mc_platform_node = fsl_mc_platform_dev->of_node;
+
+ /* Set up the iommu configuration for the devices. */
+ fsl_mc_dma_configure(mc_dev, fsl_mc_platform_node,
+ !(obj_desc->flags & DPRC_OBJ_FLAG_NO_MEM_SHAREABILITY));
/*
* The device-specific probe callback will get invoked by device_add()
@@ -656,6 +663,10 @@ void fsl_mc_device_remove(struct fsl_mc_device *mc_dev)
* The device-specific remove callback will get invoked by device_del()
*/
device_del(&mc_dev->dev);
+
+ if (strcmp(mc_dev->obj_desc.type, "dprc") != 0)
+ mc_dev->dev.iommu_fwspec = NULL;
+
put_device(&mc_dev->dev);
}
EXPORT_SYMBOL_GPL(fsl_mc_device_remove);
diff --git a/drivers/staging/fsl-mc/bus/fsl-mc-iommu.c b/drivers/staging/fsl-mc/bus/fsl-mc-iommu.c
new file mode 100644
index 0000000..bd841c9
--- /dev/null
+++ b/drivers/staging/fsl-mc/bus/fsl-mc-iommu.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ * Copyright 2017 NXP
+ * Author: Nipun Gupta <nipun.gupta@nxp.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/iommu.h>
+#include <linux/of.h>
+#include <linux/of_iommu.h>
+#include "../include/mc.h"
+
+/* Setup the IOMMU for the DPRC container */
+static const struct iommu_ops
+*fsl_mc_iommu_configure(struct fsl_mc_device *mc_dev,
+ struct device_node *fsl_mc_platform_node)
+{
+ struct of_phandle_args iommu_spec;
+ const struct iommu_ops *ops;
+ u32 iommu_phandle;
+ struct device_node *iommu_node;
+ const __be32 *map = NULL;
+ int iommu_cells, map_len, ret;
+
+ map = of_get_property(fsl_mc_platform_node, "iommu-map", &map_len);
+ if (!map)
+ return NULL;
+
+ ops = mc_dev->dev.bus->iommu_ops;
+ if (!ops || !ops->of_xlate)
+ return NULL;
+
+ iommu_phandle = be32_to_cpup(map + 1);
+ iommu_node = of_find_node_by_phandle(iommu_phandle);
+
+ if (of_property_read_u32(iommu_node, "#iommu-cells", &iommu_cells)) {
+ pr_err("%s: missing #iommu-cells property\n", iommu_node->name);
+ return NULL;
+ }
+
+ /* Initialize the fwspec */
+ ret = iommu_fwspec_init(&mc_dev->dev, &iommu_node->fwnode, ops);
+ if (ret)
+ return NULL;
+
+ /*
+ * Fill in the required stream-id before calling the iommu's
+ * ops->xlate callback.
+ */
+ iommu_spec.np = iommu_node;
+ iommu_spec.args[0] = mc_dev->icid;
+ iommu_spec.args_count = 1;
+
+ ret = ops->of_xlate(&mc_dev->dev, &iommu_spec);
+ if (ret)
+ return NULL;
+
+ of_node_put(iommu_spec.np);
+
+ return ops;
+}
+
+/* Set up DMA configuration for fsl-mc devices */
+void fsl_mc_dma_configure(struct fsl_mc_device *mc_dev,
+ struct device_node *fsl_mc_platform_node, int coherent)
+{
+ const struct iommu_ops *ops;
+
+ ops = fsl_mc_iommu_configure(mc_dev, fsl_mc_platform_node);
+
+ mc_dev->dev.coherent_dma_mask = DMA_BIT_MASK(48);
+ mc_dev->dev.dma_mask = &mc_dev->dev.coherent_dma_mask;
+ arch_setup_dma_ops(&mc_dev->dev, 0,
+ mc_dev->dev.coherent_dma_mask + 1, ops, coherent);
+}
diff --git a/drivers/staging/fsl-mc/include/mc.h b/drivers/staging/fsl-mc/include/mc.h
index 1c46c0c..fb7a3b6 100644
--- a/drivers/staging/fsl-mc/include/mc.h
+++ b/drivers/staging/fsl-mc/include/mc.h
@@ -198,4 +198,7 @@ int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev);
void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev);
+void fsl_mc_dma_configure(struct fsl_mc_device *mc_dev,
+ struct device_node *fsl_mc_platform_node, int coherent);
+
#endif /* _FSL_MC_H_ */