11ca55d50SOleksandr Tyshchenko // SPDX-License-Identifier: GPL-2.0
21ca55d50SOleksandr Tyshchenko /*
31ca55d50SOleksandr Tyshchenko * Stub IOMMU driver which does nothing.
41ca55d50SOleksandr Tyshchenko * The main purpose of it being present is to reuse generic IOMMU device tree
51ca55d50SOleksandr Tyshchenko * bindings by Xen grant DMA-mapping layer.
61ca55d50SOleksandr Tyshchenko *
71ca55d50SOleksandr Tyshchenko * Copyright (C) 2022 EPAM Systems Inc.
81ca55d50SOleksandr Tyshchenko */
91ca55d50SOleksandr Tyshchenko
101ca55d50SOleksandr Tyshchenko #include <linux/iommu.h>
111ca55d50SOleksandr Tyshchenko #include <linux/of.h>
121ca55d50SOleksandr Tyshchenko #include <linux/platform_device.h>
131ca55d50SOleksandr Tyshchenko
141ca55d50SOleksandr Tyshchenko struct grant_dma_iommu_device {
151ca55d50SOleksandr Tyshchenko struct device *dev;
161ca55d50SOleksandr Tyshchenko struct iommu_device iommu;
171ca55d50SOleksandr Tyshchenko };
181ca55d50SOleksandr Tyshchenko
grant_dma_iommu_probe_device(struct device * dev)19*2062f9fbSOleksandr Tyshchenko static struct iommu_device *grant_dma_iommu_probe_device(struct device *dev)
20*2062f9fbSOleksandr Tyshchenko {
21*2062f9fbSOleksandr Tyshchenko return ERR_PTR(-ENODEV);
22*2062f9fbSOleksandr Tyshchenko }
23*2062f9fbSOleksandr Tyshchenko
24*2062f9fbSOleksandr Tyshchenko /* Nothing is really needed here except a dummy probe_device callback */
25*2062f9fbSOleksandr Tyshchenko static const struct iommu_ops grant_dma_iommu_ops = {
26*2062f9fbSOleksandr Tyshchenko .probe_device = grant_dma_iommu_probe_device,
27*2062f9fbSOleksandr Tyshchenko };
281ca55d50SOleksandr Tyshchenko
291ca55d50SOleksandr Tyshchenko static const struct of_device_id grant_dma_iommu_of_match[] = {
301ca55d50SOleksandr Tyshchenko { .compatible = "xen,grant-dma" },
311ca55d50SOleksandr Tyshchenko { },
321ca55d50SOleksandr Tyshchenko };
331ca55d50SOleksandr Tyshchenko
grant_dma_iommu_probe(struct platform_device * pdev)341ca55d50SOleksandr Tyshchenko static int grant_dma_iommu_probe(struct platform_device *pdev)
351ca55d50SOleksandr Tyshchenko {
361ca55d50SOleksandr Tyshchenko struct grant_dma_iommu_device *mmu;
371ca55d50SOleksandr Tyshchenko int ret;
381ca55d50SOleksandr Tyshchenko
391ca55d50SOleksandr Tyshchenko mmu = devm_kzalloc(&pdev->dev, sizeof(*mmu), GFP_KERNEL);
401ca55d50SOleksandr Tyshchenko if (!mmu)
411ca55d50SOleksandr Tyshchenko return -ENOMEM;
421ca55d50SOleksandr Tyshchenko
431ca55d50SOleksandr Tyshchenko mmu->dev = &pdev->dev;
441ca55d50SOleksandr Tyshchenko
451ca55d50SOleksandr Tyshchenko ret = iommu_device_register(&mmu->iommu, &grant_dma_iommu_ops, &pdev->dev);
461ca55d50SOleksandr Tyshchenko if (ret)
471ca55d50SOleksandr Tyshchenko return ret;
481ca55d50SOleksandr Tyshchenko
491ca55d50SOleksandr Tyshchenko platform_set_drvdata(pdev, mmu);
501ca55d50SOleksandr Tyshchenko
511ca55d50SOleksandr Tyshchenko return 0;
521ca55d50SOleksandr Tyshchenko }
531ca55d50SOleksandr Tyshchenko
grant_dma_iommu_remove(struct platform_device * pdev)541ca55d50SOleksandr Tyshchenko static int grant_dma_iommu_remove(struct platform_device *pdev)
551ca55d50SOleksandr Tyshchenko {
561ca55d50SOleksandr Tyshchenko struct grant_dma_iommu_device *mmu = platform_get_drvdata(pdev);
571ca55d50SOleksandr Tyshchenko
581ca55d50SOleksandr Tyshchenko platform_set_drvdata(pdev, NULL);
591ca55d50SOleksandr Tyshchenko iommu_device_unregister(&mmu->iommu);
601ca55d50SOleksandr Tyshchenko
611ca55d50SOleksandr Tyshchenko return 0;
621ca55d50SOleksandr Tyshchenko }
631ca55d50SOleksandr Tyshchenko
641ca55d50SOleksandr Tyshchenko static struct platform_driver grant_dma_iommu_driver = {
651ca55d50SOleksandr Tyshchenko .driver = {
661ca55d50SOleksandr Tyshchenko .name = "grant-dma-iommu",
671ca55d50SOleksandr Tyshchenko .of_match_table = grant_dma_iommu_of_match,
681ca55d50SOleksandr Tyshchenko },
691ca55d50SOleksandr Tyshchenko .probe = grant_dma_iommu_probe,
701ca55d50SOleksandr Tyshchenko .remove = grant_dma_iommu_remove,
711ca55d50SOleksandr Tyshchenko };
721ca55d50SOleksandr Tyshchenko
grant_dma_iommu_init(void)731ca55d50SOleksandr Tyshchenko static int __init grant_dma_iommu_init(void)
741ca55d50SOleksandr Tyshchenko {
751ca55d50SOleksandr Tyshchenko struct device_node *iommu_np;
761ca55d50SOleksandr Tyshchenko
771ca55d50SOleksandr Tyshchenko iommu_np = of_find_matching_node(NULL, grant_dma_iommu_of_match);
781ca55d50SOleksandr Tyshchenko if (!iommu_np)
791ca55d50SOleksandr Tyshchenko return 0;
801ca55d50SOleksandr Tyshchenko
811ca55d50SOleksandr Tyshchenko of_node_put(iommu_np);
821ca55d50SOleksandr Tyshchenko
831ca55d50SOleksandr Tyshchenko return platform_driver_register(&grant_dma_iommu_driver);
841ca55d50SOleksandr Tyshchenko }
851ca55d50SOleksandr Tyshchenko subsys_initcall(grant_dma_iommu_init);
86