diff options
-rw-r--r-- | arch/arm/Kconfig | 1 | ||||
-rw-r--r-- | drivers/iommu/Kconfig | 10 | ||||
-rw-r--r-- | drivers/iommu/Makefile | 1 | ||||
-rw-r--r-- | drivers/iommu/apple_dart.c | 59 |
4 files changed, 71 insertions, 0 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 293e3e3..b4808d4 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -931,6 +931,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 3e35ce8..dabc1f9 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -14,4 +14,14 @@ config IOMMU memory if the IOMMU has been programmed to allow access to that memory. +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 af1c6bb..e3e0900 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 0000000..ff8c5fa --- /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 +}; |