sandbox_iommu.c 1.6 KB

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