vfio_amba.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (C) 2013 - Virtual Open Systems
  4. * Author: Antonios Motakis <[email protected]>
  5. */
  6. #include <linux/module.h>
  7. #include <linux/slab.h>
  8. #include <linux/vfio.h>
  9. #include <linux/pm_runtime.h>
  10. #include <linux/amba/bus.h>
  11. #include "vfio_platform_private.h"
  12. #define DRIVER_VERSION "0.10"
  13. #define DRIVER_AUTHOR "Antonios Motakis <[email protected]>"
  14. #define DRIVER_DESC "VFIO for AMBA devices - User Level meta-driver"
  15. /* probing devices from the AMBA bus */
  16. static struct resource *get_amba_resource(struct vfio_platform_device *vdev,
  17. int i)
  18. {
  19. struct amba_device *adev = (struct amba_device *) vdev->opaque;
  20. if (i == 0)
  21. return &adev->res;
  22. return NULL;
  23. }
  24. static int get_amba_irq(struct vfio_platform_device *vdev, int i)
  25. {
  26. struct amba_device *adev = (struct amba_device *) vdev->opaque;
  27. int ret = 0;
  28. if (i < AMBA_NR_IRQS)
  29. ret = adev->irq[i];
  30. /* zero is an unset IRQ for AMBA devices */
  31. return ret ? ret : -ENXIO;
  32. }
  33. static int vfio_amba_init_dev(struct vfio_device *core_vdev)
  34. {
  35. struct vfio_platform_device *vdev =
  36. container_of(core_vdev, struct vfio_platform_device, vdev);
  37. struct amba_device *adev = to_amba_device(core_vdev->dev);
  38. int ret;
  39. vdev->name = kasprintf(GFP_KERNEL, "vfio-amba-%08x", adev->periphid);
  40. if (!vdev->name)
  41. return -ENOMEM;
  42. vdev->opaque = (void *) adev;
  43. vdev->flags = VFIO_DEVICE_FLAGS_AMBA;
  44. vdev->get_resource = get_amba_resource;
  45. vdev->get_irq = get_amba_irq;
  46. vdev->reset_required = false;
  47. ret = vfio_platform_init_common(vdev);
  48. if (ret)
  49. kfree(vdev->name);
  50. return ret;
  51. }
  52. static const struct vfio_device_ops vfio_amba_ops;
  53. static int vfio_amba_probe(struct amba_device *adev, const struct amba_id *id)
  54. {
  55. struct vfio_platform_device *vdev;
  56. int ret;
  57. vdev = vfio_alloc_device(vfio_platform_device, vdev, &adev->dev,
  58. &vfio_amba_ops);
  59. if (IS_ERR(vdev))
  60. return PTR_ERR(vdev);
  61. ret = vfio_register_group_dev(&vdev->vdev);
  62. if (ret)
  63. goto out_put_vdev;
  64. pm_runtime_enable(&adev->dev);
  65. dev_set_drvdata(&adev->dev, vdev);
  66. return 0;
  67. out_put_vdev:
  68. vfio_put_device(&vdev->vdev);
  69. return ret;
  70. }
  71. static void vfio_amba_release_dev(struct vfio_device *core_vdev)
  72. {
  73. struct vfio_platform_device *vdev =
  74. container_of(core_vdev, struct vfio_platform_device, vdev);
  75. vfio_platform_release_common(vdev);
  76. kfree(vdev->name);
  77. vfio_free_device(core_vdev);
  78. }
  79. static void vfio_amba_remove(struct amba_device *adev)
  80. {
  81. struct vfio_platform_device *vdev = dev_get_drvdata(&adev->dev);
  82. vfio_unregister_group_dev(&vdev->vdev);
  83. pm_runtime_disable(vdev->device);
  84. vfio_put_device(&vdev->vdev);
  85. }
  86. static const struct vfio_device_ops vfio_amba_ops = {
  87. .name = "vfio-amba",
  88. .init = vfio_amba_init_dev,
  89. .release = vfio_amba_release_dev,
  90. .open_device = vfio_platform_open_device,
  91. .close_device = vfio_platform_close_device,
  92. .ioctl = vfio_platform_ioctl,
  93. .read = vfio_platform_read,
  94. .write = vfio_platform_write,
  95. .mmap = vfio_platform_mmap,
  96. };
  97. static const struct amba_id pl330_ids[] = {
  98. { 0, 0 },
  99. };
  100. MODULE_DEVICE_TABLE(amba, pl330_ids);
  101. static struct amba_driver vfio_amba_driver = {
  102. .probe = vfio_amba_probe,
  103. .remove = vfio_amba_remove,
  104. .id_table = pl330_ids,
  105. .drv = {
  106. .name = "vfio-amba",
  107. .owner = THIS_MODULE,
  108. },
  109. .driver_managed_dma = true,
  110. };
  111. module_amba_driver(vfio_amba_driver);
  112. MODULE_VERSION(DRIVER_VERSION);
  113. MODULE_LICENSE("GPL v2");
  114. MODULE_AUTHOR(DRIVER_AUTHOR);
  115. MODULE_DESCRIPTION(DRIVER_DESC);