summaryrefslogtreecommitdiff
path: root/drivers/iommu/sandbox_iommu.c
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2023-01-27 14:48:22 -0500
committerTom Rini <trini@konsulko.com>2023-01-27 14:48:22 -0500
commitf147aa80f52989c7455022ca1ab959e8545feccc (patch)
tree5e513d166bf3859bf649601099110312406c4c34 /drivers/iommu/sandbox_iommu.c
parentaa7c61f62923a1c9e9ec7f588ad37016d8c7323c (diff)
parente330c8b83e8784d23614f80ca3f12b11ceb515d8 (diff)
Merge branch '2023-01-27-apple-soc-updates'
First, to quote the author: This series adds support for the PCIe controller found on Apple M1 and M2 machines and enables support for PCIe XHCI controllers. This makes the type-A USB ports on the M1 Mac mini work. Since the use of Apples DART IOMMU is mandatory (these PCIe DARTs don't support bypass mode), this adds DMA mapping operations to the IOMMU uclass and implements them for the Apple DART. It modifies the XHCI driver code to go map DMA buffers through the IOMMU if there is one. Since the M1 Mac mini now has two types of XHCI controllers with different number of ports (2 for the DWC3 controllers, 8 for the Fresco Logic PCIe controller) this uncovered an issue in with the way the hub descriptor is implemented in the XHCI driver. Second, Mark also fixes some Apple-specific instances of CONFIG_IS_ENABLED that should be IS_ENABLED.
Diffstat (limited to 'drivers/iommu/sandbox_iommu.c')
-rw-r--r--drivers/iommu/sandbox_iommu.c58
1 files changed, 58 insertions, 0 deletions
diff --git a/drivers/iommu/sandbox_iommu.c b/drivers/iommu/sandbox_iommu.c
index c8161a40aef..6ceb7fd5ec3 100644
--- a/drivers/iommu/sandbox_iommu.c
+++ b/drivers/iommu/sandbox_iommu.c
@@ -5,6 +5,61 @@
#include <common.h>
#include <dm.h>
+#include <iommu.h>
+#include <lmb.h>
+#include <asm/io.h>
+#include <linux/sizes.h>
+
+#define IOMMU_PAGE_SIZE SZ_4K
+
+struct sandbox_iommu_priv {
+ struct lmb lmb;
+};
+
+static dma_addr_t sandbox_iommu_map(struct udevice *dev, void *addr,
+ size_t size)
+{
+ struct sandbox_iommu_priv *priv = dev_get_priv(dev);
+ phys_addr_t paddr, dva;
+ phys_size_t psize, off;
+
+ paddr = ALIGN_DOWN(virt_to_phys(addr), IOMMU_PAGE_SIZE);
+ off = virt_to_phys(addr) - paddr;
+ psize = ALIGN(size + off, IOMMU_PAGE_SIZE);
+
+ dva = lmb_alloc(&priv->lmb, psize, IOMMU_PAGE_SIZE);
+
+ return dva + off;
+}
+
+static void sandbox_iommu_unmap(struct udevice *dev, dma_addr_t addr,
+ size_t size)
+{
+ struct sandbox_iommu_priv *priv = dev_get_priv(dev);
+ phys_addr_t dva;
+ phys_size_t psize;
+
+ dva = ALIGN_DOWN(addr, IOMMU_PAGE_SIZE);
+ psize = size + (addr - dva);
+ psize = ALIGN(psize, IOMMU_PAGE_SIZE);
+
+ lmb_free(&priv->lmb, dva, psize);
+}
+
+static struct iommu_ops sandbox_iommu_ops = {
+ .map = sandbox_iommu_map,
+ .unmap = sandbox_iommu_unmap,
+};
+
+static int sandbox_iommu_probe(struct udevice *dev)
+{
+ struct sandbox_iommu_priv *priv = dev_get_priv(dev);
+
+ lmb_init(&priv->lmb);
+ lmb_add(&priv->lmb, 0x89abc000, SZ_16K);
+
+ return 0;
+}
static const struct udevice_id sandbox_iommu_ids[] = {
{ .compatible = "sandbox,iommu" },
@@ -15,4 +70,7 @@ U_BOOT_DRIVER(sandbox_iommu) = {
.name = "sandbox_iommu",
.id = UCLASS_IOMMU,
.of_match = sandbox_iommu_ids,
+ .priv_auto = sizeof(struct sandbox_iommu_priv),
+ .ops = &sandbox_iommu_ops,
+ .probe = sandbox_iommu_probe,
};