uboot/drivers/iommu/sandbox_iommu.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2021 Mark Kettenis <kettenis@openbsd.org>
   4 */
   5
   6#include <common.h>
   7#include <dm.h>
   8#include <iommu.h>
   9#include <lmb.h>
  10#include <asm/io.h>
  11#include <linux/sizes.h>
  12
  13#define IOMMU_PAGE_SIZE         SZ_4K
  14
  15struct sandbox_iommu_priv {
  16        struct lmb lmb;
  17};
  18
  19static dma_addr_t sandbox_iommu_map(struct udevice *dev, void *addr,
  20                                    size_t size)
  21{
  22        struct sandbox_iommu_priv *priv = dev_get_priv(dev);
  23        phys_addr_t paddr, dva;
  24        phys_size_t psize, off;
  25
  26        paddr = ALIGN_DOWN(virt_to_phys(addr), IOMMU_PAGE_SIZE);
  27        off = virt_to_phys(addr) - paddr;
  28        psize = ALIGN(size + off, IOMMU_PAGE_SIZE);
  29
  30        dva = lmb_alloc(&priv->lmb, psize, IOMMU_PAGE_SIZE);
  31
  32        return dva + off;
  33}
  34
  35static void sandbox_iommu_unmap(struct udevice *dev, dma_addr_t addr,
  36                                size_t size)
  37{
  38        struct sandbox_iommu_priv *priv = dev_get_priv(dev);
  39        phys_addr_t dva;
  40        phys_size_t psize;
  41
  42        dva = ALIGN_DOWN(addr, IOMMU_PAGE_SIZE);
  43        psize = size + (addr - dva);
  44        psize = ALIGN(psize, IOMMU_PAGE_SIZE);
  45
  46        lmb_free(&priv->lmb, dva, psize);
  47}
  48
  49static struct iommu_ops sandbox_iommu_ops = {
  50        .map = sandbox_iommu_map,
  51        .unmap = sandbox_iommu_unmap,
  52};
  53
  54static int sandbox_iommu_probe(struct udevice *dev)
  55{
  56        struct sandbox_iommu_priv *priv = dev_get_priv(dev);
  57
  58        lmb_init(&priv->lmb);
  59        lmb_add(&priv->lmb, 0x89abc000, SZ_16K);
  60
  61        return 0;
  62}
  63
  64static const struct udevice_id sandbox_iommu_ids[] = {
  65        { .compatible = "sandbox,iommu" },
  66        { /* sentinel */ }
  67};
  68
  69U_BOOT_DRIVER(sandbox_iommu) = {
  70        .name = "sandbox_iommu",
  71        .id = UCLASS_IOMMU,
  72        .of_match = sandbox_iommu_ids,
  73        .priv_auto = sizeof(struct sandbox_iommu_priv),
  74        .ops = &sandbox_iommu_ops,
  75        .probe = sandbox_iommu_probe,
  76};
  77