diff options
author | Mark Kettenis <kettenis@openbsd.org> | 2023-01-21 22:27:53 +0300 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2023-01-27 22:47:58 +0300 |
commit | 49a1a4becb2deaeb5764dfe4022807b147b87b9c (patch) | |
tree | 1d383445294030000b4662e1af919912647d0e80 /drivers/iommu/sandbox_iommu.c | |
parent | dd6b68ed4f5bba78c0cd9765fa48b10cb1542dc7 (diff) | |
download | u-boot-49a1a4becb2deaeb5764dfe4022807b147b87b9c.tar.xz |
test: Add test for IOMMU uclass map/unmap ops
Test that the map and unmap operations work for devices that
have DMA translated by an IOMMU and devices that don't have
DMA translated by an IOMMU.
Signed-off-by: Mark Kettenis <kettenis@openbsd.org>
Reviewed-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'drivers/iommu/sandbox_iommu.c')
-rw-r--r-- | drivers/iommu/sandbox_iommu.c | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/drivers/iommu/sandbox_iommu.c b/drivers/iommu/sandbox_iommu.c index c8161a40ae..6ceb7fd5ec 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, }; |