From 40dbf03d7d2dd2b5516f797069e3ea830db6fecc Mon Sep 17 00:00:00 2001 From: Mark Kettenis Date: Sat, 23 Oct 2021 16:58:01 +0200 Subject: iommu: Add IOMMU uclass This uclass is intended to manage IOMMUs on systems where the IOMMUs are not in bypass mode by default. In that case U-Boot cannot ignore the IOMMUs if it wants to use devices that need to do DMA and sit behind such an IOMMU. This initial IOMMU uclass implementation does not implement and device ops and is intended for IOMMUs that have a bypass mode that does not require address translation. Support for IOMMUs that do require address translation is planned and device ops will be defined when support for such IOMMUs will be added. Signed-off-by: Mark Kettenis Reviewed-by: Simon Glass --- drivers/Kconfig | 2 ++ drivers/Makefile | 1 + drivers/core/device.c | 8 ++++++++ drivers/iommu/Kconfig | 17 +++++++++++++++++ drivers/iommu/Makefile | 3 +++ drivers/iommu/iommu-uclass.c | 45 ++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 76 insertions(+) create mode 100644 drivers/iommu/Kconfig create mode 100644 drivers/iommu/Makefile create mode 100644 drivers/iommu/iommu-uclass.c (limited to 'drivers') diff --git a/drivers/Kconfig b/drivers/Kconfig index 417d6f88c29..b26ca8cf70c 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -50,6 +50,8 @@ source "drivers/i2c/Kconfig" source "drivers/input/Kconfig" +source "drivers/iommu/Kconfig" + source "drivers/led/Kconfig" source "drivers/mailbox/Kconfig" diff --git a/drivers/Makefile b/drivers/Makefile index 4cbc40787db..4e7cf284405 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -102,6 +102,7 @@ obj-y += mtd/ obj-y += pwm/ obj-y += reset/ obj-y += input/ +obj-y += iommu/ # SOC specific infrastructure drivers. obj-y += smem/ obj-y += thermal/ diff --git a/drivers/core/device.c b/drivers/core/device.c index d7a778a2413..efd07176e37 100644 --- a/drivers/core/device.c +++ b/drivers/core/device.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -543,6 +544,13 @@ int device_probe(struct udevice *dev) goto fail; } + if (CONFIG_IS_ENABLED(IOMMU) && dev->parent && + (device_get_uclass_id(dev) != UCLASS_IOMMU)) { + ret = dev_iommu_enable(dev); + if (ret) + goto fail; + } + ret = device_get_dma_constraints(dev); if (ret) goto fail; diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig new file mode 100644 index 00000000000..3e35ce8fcc8 --- /dev/null +++ b/drivers/iommu/Kconfig @@ -0,0 +1,17 @@ +# +# IOMMU devices +# + +menu "IOMMU device drivers" + +config IOMMU + bool "Enable Driver Model for IOMMU drivers" + depends on DM + help + Enable driver model for IOMMU devices. An IOMMU maps device + virtiual memory addresses to physical addresses. Devices + that sit behind an IOMMU can typically only access physical + memory if the IOMMU has been programmed to allow access to + that memory. + +endmenu diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile new file mode 100644 index 00000000000..f1ceb101507 --- /dev/null +++ b/drivers/iommu/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0+ + +obj-$(CONFIG_IOMMU) += iommu-uclass.o diff --git a/drivers/iommu/iommu-uclass.c b/drivers/iommu/iommu-uclass.c new file mode 100644 index 00000000000..ed917b3c3e8 --- /dev/null +++ b/drivers/iommu/iommu-uclass.c @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2021 Mark Kettenis + */ + +#define LOG_CATEGORY UCLASS_IOMMU + +#include +#include + +#if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) +int dev_iommu_enable(struct udevice *dev) +{ + struct ofnode_phandle_args args; + struct udevice *dev_iommu; + int i, count, ret = 0; + + count = dev_count_phandle_with_args(dev, "iommus", + "#iommu-cells", 0); + for (i = 0; i < count; i++) { + ret = dev_read_phandle_with_args(dev, "iommus", + "#iommu-cells", 0, i, &args); + if (ret) { + debug("%s: dev_read_phandle_with_args failed: %d\n", + __func__, ret); + return ret; + } + + ret = uclass_get_device_by_ofnode(UCLASS_IOMMU, args.node, + &dev_iommu); + if (ret) { + debug("%s: uclass_get_device_by_ofnode failed: %d\n", + __func__, ret); + return ret; + } + } + + return 0; +} +#endif + +UCLASS_DRIVER(iommu) = { + .id = UCLASS_IOMMU, + .name = "iommu", +}; -- cgit v1.3.1