diff mbox series

[v2,5/7] iommu: Add Apple DART driver

Message ID 20211003183050.67925-6-kettenis@openbsd.org
State Superseded
Delegated to: Tom Rini
Headers show
Series Apple M1 Support | expand

Commit Message

Mark Kettenis Oct. 3, 2021, 6:30 p.m. UTC
The DART is an IOMMU that is used on Apple's M1 SoC.  This driver
configures the DART such that it operates in bypass mode which is
enough to support DMA for the USB3 ports integrated on the SoC.

Signed-off-by: Mark Kettenis <kettenis@openbsd.org>
---
 arch/arm/Kconfig           |  1 +
 drivers/iommu/Kconfig      | 10 +++++++
 drivers/iommu/Makefile     |  1 +
 drivers/iommu/apple_dart.c | 59 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 71 insertions(+)
 create mode 100644 drivers/iommu/apple_dart.c

Comments

Simon Glass Oct. 11, 2021, 5 p.m. UTC | #1
On Sun, 3 Oct 2021 at 12:34, Mark Kettenis <kettenis@openbsd.org> wrote:
>
> The DART is an IOMMU that is used on Apple's M1 SoC.  This driver
> configures the DART such that it operates in bypass mode which is
> enough to support DMA for the USB3 ports integrated on the SoC.
>
> Signed-off-by: Mark Kettenis <kettenis@openbsd.org>
> ---
>  arch/arm/Kconfig           |  1 +
>  drivers/iommu/Kconfig      | 10 +++++++
>  drivers/iommu/Makefile     |  1 +
>  drivers/iommu/apple_dart.c | 59 ++++++++++++++++++++++++++++++++++++++
>  4 files changed, 71 insertions(+)
>  create mode 100644 drivers/iommu/apple_dart.c
>

Reviewed-by: Simon Glass <sjg@chromium.org>
diff mbox series

Patch

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 876d9c4044..91bf6a122a 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -906,6 +906,7 @@  config ARCH_APPLE
 	select DM_SERIAL
 	select DM_USB
 	select DM_VIDEO
+	select IOMMU
 	select LINUX_KERNEL_IMAGE_HEADER
 	select OF_CONTROL
 	select OF_BOARD
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index 8cb377560e..51694c168c 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -10,4 +10,14 @@  config IOMMU
 	help
 	  Enable driver model for IOMMU devices.
 
+config APPLE_DART
+	bool "Apple DART support"
+	depends on IOMMU && ARCH_APPLE
+	default y
+	help
+	  Enable support for the DART on Apple SoCs.  The DART is Apple's
+	  IOMMU implementation.  The driver performs the necessary
+	  configuration to put the DART into bypass mode such that it can
+	  be used transparently by U-Boot.
+
 endmenu
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index af1c6bbb7a..e3e0900e17 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -2,4 +2,5 @@ 
 
 obj-$(CONFIG_IOMMU) += iommu-uclass.o
 
+obj-$(CONFIG_APPLE_DART) += apple_dart.o
 obj-$(CONFIG_SANDBOX) += sandbox_iommu.o
diff --git a/drivers/iommu/apple_dart.c b/drivers/iommu/apple_dart.c
new file mode 100644
index 0000000000..ff8c5fa62c
--- /dev/null
+++ b/drivers/iommu/apple_dart.c
@@ -0,0 +1,59 @@ 
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2021 Mark Kettenis <kettenis@openbsd.org>
+ */
+
+#include <common.h>
+#include <cpu_func.h>
+#include <dm.h>
+#include <asm/io.h>
+
+#define DART_PARAMS2		0x0004
+#define  DART_PARAMS2_BYPASS_SUPPORT	BIT(0)
+#define DART_TLB_OP		0x0020
+#define  DART_TLB_OP_OPMASK	(0xfff << 20)
+#define  DART_TLB_OP_FLUSH	(0x001 << 20)
+#define  DART_TLB_OP_BUSY	BIT(2)
+#define DART_TLB_OP_SIDMASK	0x0034
+#define DART_ERROR_STATUS	0x0040
+#define DART_TCR(sid)		(0x0100 + 4 * (sid))
+#define  DART_TCR_TRANSLATE_ENABLE	BIT(7)
+#define  DART_TCR_BYPASS_DART		BIT(8)
+#define  DART_TCR_BYPASS_DAPF		BIT(12)
+#define DART_TTBR(sid, idx)	(0x0200 + 16 * (sid) + 4 * (idx))
+#define  DART_TTBR_VALID	BIT(31)
+#define  DART_TTBR_SHIFT	12
+
+static int apple_dart_probe(struct udevice *dev)
+{
+	void *base;
+	int sid, i;
+
+	base = dev_read_addr_ptr(dev);
+	if (!base)
+		return -EINVAL;
+
+	u32 params2 = readl(base + DART_PARAMS2);
+	if (params2 & DART_PARAMS2_BYPASS_SUPPORT) {
+		for (sid = 0; sid < 16; sid++) {
+			writel(DART_TCR_BYPASS_DART | DART_TCR_BYPASS_DAPF,
+			       base + DART_TCR(sid));
+			for (i = 0; i < 4; i++)
+				writel(0, base + DART_TTBR(sid, i));
+		}
+	}
+
+	return 0;
+}
+
+static const struct udevice_id apple_dart_ids[] = {
+	{ .compatible = "apple,t8103-dart" },
+	{ /* sentinel */ }
+};
+
+U_BOOT_DRIVER(apple_dart) = {
+	.name = "apple_dart",
+	.id = UCLASS_IOMMU,
+	.of_match = apple_dart_ids,
+	.probe = apple_dart_probe
+};