|
@@ -1253,6 +1253,49 @@ static int omap_iommu_domain_has_cap(struct iommu_domain *domain,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static int omap_iommu_add_device(struct device *dev)
|
|
|
+{
|
|
|
+ struct omap_iommu_arch_data *arch_data;
|
|
|
+ struct device_node *np;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Allocate the archdata iommu structure for DT-based devices.
|
|
|
+ *
|
|
|
+ * TODO: Simplify this when removing non-DT support completely from the
|
|
|
+ * IOMMU users.
|
|
|
+ */
|
|
|
+ if (!dev->of_node)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ np = of_parse_phandle(dev->of_node, "iommus", 0);
|
|
|
+ if (!np)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ arch_data = kzalloc(sizeof(*arch_data), GFP_KERNEL);
|
|
|
+ if (!arch_data) {
|
|
|
+ of_node_put(np);
|
|
|
+ return -ENOMEM;
|
|
|
+ }
|
|
|
+
|
|
|
+ arch_data->name = kstrdup(dev_name(dev), GFP_KERNEL);
|
|
|
+ dev->archdata.iommu = arch_data;
|
|
|
+
|
|
|
+ of_node_put(np);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static void omap_iommu_remove_device(struct device *dev)
|
|
|
+{
|
|
|
+ struct omap_iommu_arch_data *arch_data = dev->archdata.iommu;
|
|
|
+
|
|
|
+ if (!dev->of_node || !arch_data)
|
|
|
+ return;
|
|
|
+
|
|
|
+ kfree(arch_data->name);
|
|
|
+ kfree(arch_data);
|
|
|
+}
|
|
|
+
|
|
|
static struct iommu_ops omap_iommu_ops = {
|
|
|
.domain_init = omap_iommu_domain_init,
|
|
|
.domain_destroy = omap_iommu_domain_destroy,
|
|
@@ -1262,6 +1305,8 @@ static struct iommu_ops omap_iommu_ops = {
|
|
|
.unmap = omap_iommu_unmap,
|
|
|
.iova_to_phys = omap_iommu_iova_to_phys,
|
|
|
.domain_has_cap = omap_iommu_domain_has_cap,
|
|
|
+ .add_device = omap_iommu_add_device,
|
|
|
+ .remove_device = omap_iommu_remove_device,
|
|
|
.pgsize_bitmap = OMAP_IOMMU_PGSIZES,
|
|
|
};
|
|
|
|